1*4882a593Smuzhiyuninherit terminal 2*4882a593Smuzhiyun 3*4882a593SmuzhiyunDEVSHELL = "${SHELL}" 4*4882a593Smuzhiyun 5*4882a593Smuzhiyunpython do_devshell () { 6*4882a593Smuzhiyun if d.getVarFlag("do_devshell", "manualfakeroot"): 7*4882a593Smuzhiyun d.prependVar("DEVSHELL", "pseudo ") 8*4882a593Smuzhiyun fakeenv = d.getVar("FAKEROOTENV").split() 9*4882a593Smuzhiyun for f in fakeenv: 10*4882a593Smuzhiyun k = f.split("=") 11*4882a593Smuzhiyun d.setVar(k[0], k[1]) 12*4882a593Smuzhiyun d.appendVar("OE_TERMINAL_EXPORTS", " " + k[0]) 13*4882a593Smuzhiyun d.delVarFlag("do_devshell", "fakeroot") 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun oe_terminal(d.getVar('DEVSHELL'), 'OpenEmbedded Developer Shell', d) 16*4882a593Smuzhiyun} 17*4882a593Smuzhiyun 18*4882a593Smuzhiyunaddtask devshell after do_patch do_prepare_recipe_sysroot 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun# The directory that the terminal starts in 21*4882a593SmuzhiyunDEVSHELL_STARTDIR ?= "${S}" 22*4882a593Smuzhiyundo_devshell[dirs] = "${DEVSHELL_STARTDIR}" 23*4882a593Smuzhiyundo_devshell[nostamp] = "1" 24*4882a593Smuzhiyundo_devshell[network] = "1" 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun# devshell and fakeroot/pseudo need careful handling since only the final 27*4882a593Smuzhiyun# command should run under fakeroot emulation, any X connection should 28*4882a593Smuzhiyun# be done as the normal user. We therfore carefully construct the envionment 29*4882a593Smuzhiyun# manually 30*4882a593Smuzhiyunpython () { 31*4882a593Smuzhiyun if d.getVarFlag("do_devshell", "fakeroot"): 32*4882a593Smuzhiyun # We need to signal our code that we want fakeroot however we 33*4882a593Smuzhiyun # can't manipulate the environment and variables here yet (see YOCTO #4795) 34*4882a593Smuzhiyun d.setVarFlag("do_devshell", "manualfakeroot", "1") 35*4882a593Smuzhiyun d.delVarFlag("do_devshell", "fakeroot") 36*4882a593Smuzhiyun} 37*4882a593Smuzhiyun 38*4882a593Smuzhiyundef pydevshell(d): 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun import code 41*4882a593Smuzhiyun import select 42*4882a593Smuzhiyun import signal 43*4882a593Smuzhiyun import termios 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun m, s = os.openpty() 46*4882a593Smuzhiyun sname = os.ttyname(s) 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun def noechoicanon(fd): 49*4882a593Smuzhiyun old = termios.tcgetattr(fd) 50*4882a593Smuzhiyun old[3] = old[3] &~ termios.ECHO &~ termios.ICANON 51*4882a593Smuzhiyun # &~ termios.ISIG 52*4882a593Smuzhiyun termios.tcsetattr(fd, termios.TCSADRAIN, old) 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun # No echo or buffering over the pty 55*4882a593Smuzhiyun noechoicanon(s) 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun pid = os.fork() 58*4882a593Smuzhiyun if pid: 59*4882a593Smuzhiyun os.close(m) 60*4882a593Smuzhiyun oe_terminal("oepydevshell-internal.py %s %d" % (sname, pid), 'OpenEmbedded Developer PyShell', d) 61*4882a593Smuzhiyun os._exit(0) 62*4882a593Smuzhiyun else: 63*4882a593Smuzhiyun os.close(s) 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun os.dup2(m, sys.stdin.fileno()) 66*4882a593Smuzhiyun os.dup2(m, sys.stdout.fileno()) 67*4882a593Smuzhiyun os.dup2(m, sys.stderr.fileno()) 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun bb.utils.nonblockingfd(sys.stdout) 70*4882a593Smuzhiyun bb.utils.nonblockingfd(sys.stderr) 71*4882a593Smuzhiyun bb.utils.nonblockingfd(sys.stdin) 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun _context = { 74*4882a593Smuzhiyun "os": os, 75*4882a593Smuzhiyun "bb": bb, 76*4882a593Smuzhiyun "time": time, 77*4882a593Smuzhiyun "d": d, 78*4882a593Smuzhiyun } 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun ps1 = "pydevshell> " 81*4882a593Smuzhiyun ps2 = "... " 82*4882a593Smuzhiyun buf = [] 83*4882a593Smuzhiyun more = False 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun i = code.InteractiveInterpreter(locals=_context) 86*4882a593Smuzhiyun print("OE PyShell (PN = %s)\n" % d.getVar("PN")) 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun def prompt(more): 89*4882a593Smuzhiyun if more: 90*4882a593Smuzhiyun prompt = ps2 91*4882a593Smuzhiyun else: 92*4882a593Smuzhiyun prompt = ps1 93*4882a593Smuzhiyun sys.stdout.write(prompt) 94*4882a593Smuzhiyun sys.stdout.flush() 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun # Restore Ctrl+C since bitbake masks this 97*4882a593Smuzhiyun def signal_handler(signal, frame): 98*4882a593Smuzhiyun raise KeyboardInterrupt 99*4882a593Smuzhiyun signal.signal(signal.SIGINT, signal_handler) 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun child = None 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun prompt(more) 104*4882a593Smuzhiyun while True: 105*4882a593Smuzhiyun try: 106*4882a593Smuzhiyun try: 107*4882a593Smuzhiyun (r, _, _) = select.select([sys.stdin], [], [], 1) 108*4882a593Smuzhiyun if not r: 109*4882a593Smuzhiyun continue 110*4882a593Smuzhiyun line = sys.stdin.readline().strip() 111*4882a593Smuzhiyun if not line: 112*4882a593Smuzhiyun prompt(more) 113*4882a593Smuzhiyun continue 114*4882a593Smuzhiyun except EOFError as e: 115*4882a593Smuzhiyun sys.stdout.write("\n") 116*4882a593Smuzhiyun sys.stdout.flush() 117*4882a593Smuzhiyun except (OSError, IOError) as e: 118*4882a593Smuzhiyun if e.errno == 11: 119*4882a593Smuzhiyun continue 120*4882a593Smuzhiyun if e.errno == 5: 121*4882a593Smuzhiyun return 122*4882a593Smuzhiyun raise 123*4882a593Smuzhiyun else: 124*4882a593Smuzhiyun if not child: 125*4882a593Smuzhiyun child = int(line) 126*4882a593Smuzhiyun continue 127*4882a593Smuzhiyun buf.append(line) 128*4882a593Smuzhiyun source = "\n".join(buf) 129*4882a593Smuzhiyun more = i.runsource(source, "<pyshell>") 130*4882a593Smuzhiyun if not more: 131*4882a593Smuzhiyun buf = [] 132*4882a593Smuzhiyun sys.stderr.flush() 133*4882a593Smuzhiyun prompt(more) 134*4882a593Smuzhiyun except KeyboardInterrupt: 135*4882a593Smuzhiyun i.write("\nKeyboardInterrupt\n") 136*4882a593Smuzhiyun buf = [] 137*4882a593Smuzhiyun more = False 138*4882a593Smuzhiyun prompt(more) 139*4882a593Smuzhiyun except SystemExit: 140*4882a593Smuzhiyun # Easiest way to ensure everything exits 141*4882a593Smuzhiyun os.kill(child, signal.SIGTERM) 142*4882a593Smuzhiyun break 143*4882a593Smuzhiyun 144*4882a593Smuzhiyunpython do_pydevshell() { 145*4882a593Smuzhiyun import signal 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun try: 148*4882a593Smuzhiyun pydevshell(d) 149*4882a593Smuzhiyun except SystemExit: 150*4882a593Smuzhiyun # Stop the SIGTERM above causing an error exit code 151*4882a593Smuzhiyun return 152*4882a593Smuzhiyun finally: 153*4882a593Smuzhiyun return 154*4882a593Smuzhiyun} 155*4882a593Smuzhiyunaddtask pydevshell after do_patch 156*4882a593Smuzhiyun 157*4882a593Smuzhiyundo_pydevshell[nostamp] = "1" 158*4882a593Smuzhiyundo_pydevshell[network] = "1" 159