Question

Hi I'm writing a psudo-terminal that can live in a tty and spawn a second tty which is filters input and output from

I'm writing it in python for now, spawning the second tty and reading and writing is easy

but when I read, the read does not end, it waits for more input.

import subprocess

pfd = subprocess.Popen(['/bin/sh'], shell=True, 
    stdout=subprocess.PIPE, stdin=subprocess.PIPE)

cmd = "ls" 

pfd.stdin.write(cmd + '\n')

out = ''
while 1: 
    c = pfd.stdout.read(1)
    if not c: # if end of output (this never happends)
        break 
    if c == '\n': # print line when found
        print repr(out)
        out = ''
    else:
        out += c

----------------------------- outputs ------------------------

intty $ python intty.py 
'intty.py'
'testA_blank'
'testB_blank'
(hangs here does not return)

it looks like it's reaching the end of hte buffer and instead of returning None or '' it hangs waiting for more input.

what should I be looking for to see if the output has completed? the end of the buffer? a non-printable character?

---------------- edit -------------

this happends also when I run xpcshell instead of ls, I'm assuming these interactive programs have some way of knowing to display the prompt again, strangly the prompt, in this case "js>" never apears

Was it helpful?

Solution

Well, your output actually hasn't completed. Because you spawned /bin/sh, the shell is still running after "ls" completes. There is no EOF indicator, because it's still running.

Why not simply run /bin/ls?

You could do something like

pfd = subprocess.Popen(['ls'], stdout=subprocess.PIPE, stdin=subprocess.PIPE)

out, err_output = pfd.communicate()

This also highlights subprocess.communicate, which is a safer way to get output (For outputs which fit in memory, anyway) from a single program run. This will return only when the program has finished running.

Alternately, you -could- read linewise from the shell, but you'd be looking for a special shell sequence like the sh~# line which could easily show up in program output. Thus, running a shell is probably a bad idea all around.


Edit Here is what I was referring to, but it's still not really the best solution, as it has a LOT of caveats:

while 1: 
    c = pfd.stdout.read(1)
    if not c:
        break
    elif c == '\n': # print line when found
        print repr(out)
        out = ''
    else:
        out += c
        if out.strip() == 'sh#':
            break

Note that this will break out if any other command outputs 'sh#' at the beginning of the line, and also if for some reason the output is different from expected, you will enter the same blocking situation as before. This is why it's a very sub-optimal situation for a shell.

OTHER TIPS

For applications like a shell, the output will not end until the shell ends. Either use select.select() to check if it has more output waiting for you, or end the process.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top