-
Notifications
You must be signed in to change notification settings - Fork 0
/
aio_bash.py
executable file
·70 lines (51 loc) · 1.47 KB
/
aio_bash.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Dont kjnow who this would help, but this explain how to "shell out" to bash with
multiplexing using asyncio in python... just for fun
"""
import os
import pty
import select
import sys
import termios
import tty
from subprocess import Popen
import click
import asyncio
from functools import wraps
def syncify(fnc):
@wraps(fnc)
def _(*a, **b):
return asyncio.run(fnc(*a, **b))
return _
def fd2fd(fdo, fdd):
if o := os.read(fdo, 10240):
os.write(fdd, o)
@click.command()
@click.argument("shell", default="bash")
@syncify
async def bash(shell):
command = [shell] # "bash"
old_tty = termios.tcgetattr(sys.stdin)
tty.setraw(sys.stdin.fileno())
loop = asyncio.get_running_loop()
# open pseudo-terminal to interact with subprocess
master_fd, follower_fd = pty.openpty()
loop.add_reader(master_fd, fd2fd, master_fd, sys.stdout.fileno())
loop.add_reader(sys.stdin.fileno(), fd2fd, sys.stdin.fileno(), master_fd)
p = await asyncio.subprocess.create_subprocess_exec(
*command,
stdin=follower_fd,
stdout=follower_fd,
stderr=follower_fd,
)
estatus = await p.wait()
loop.remove_reader(master_fd)
loop.remove_reader(sys.stdin.fileno())
# restore tty settings back
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
return estatus
if __name__ == "__main__":
the_bash = bash()
exitv = asyncio.run(the_bash)