Creating "Scrollable" Output in Command Line Programs - python

I have a program that outputs anywhere from 300-1000 lines of data. Rather than have it all output at once, I'd like it to have a manpages-like interface where it will display the first 50 or so lines of input and then the user can press 'f' or 'b' to navigate through the pages. Is there a way to do this in Python?
Note: I want to distribute the program, and I don't want to force users to pipe the output to less/more. Moreover, the output occurs in the middle of the program and is not the only output of the program, so I'm not sure if that would work any way.

You could do something very rudimentary like:
# pseudocode
def display_text(text):
lines = text.splitlines()
while lines remaining:
display next N lines
wait for key press
To "wait for key press", you could do something like this: http://www.daniweb.com/software-development/python/threads/123777/press-any-key-to-continue

Note: I would never do this, and I think it is very bad UIX, but ...
pager = subprocess.Popen(['less'], stdin=subprocess.PIPE)
Then write all of your command's output to the file-like object: pager.stdin

Related

Not able to erase from input buffer when the line wraps (pexpect)

I am using a script to connect to another server. The skeleton looks something like this:
import pexpect
...
child = pexpect.spawn(f"""ssh {username}#{host}""")
child.setwinsize(136,1000)
child.expect("Password:")
child.sendline(pwd)
However, when I enter a very long input it wraps around to the next line. The problem I am facing is that when I try to erase it (backspace-it), it doesn't take me to the previous line. So the input stays as is on the previous line. But this is how it is shown to me in the terminal, behind the scene the input gets backspaced (if that's a word).

PwnTools recv() on output that expects input directly after

Hi I have a problem that I cannot seem to find any solution for.
(Maybe i'm just horrible at phrasing searches correctly in english)
I'm trying to execute a binary from python using pwntools and reading its output completely before sending some input myself.
The output from my binary is as follows:
Testmessage1
Testmessage2
Enter input: <binary expects me to input stuff here>
Where I would like to read the first line, the second line and the output part of the third line (with ':' being the last character).
The third line of the output does not contain a newline at the end and expects the user to make an input directly. However, I'm not able to read the output contents that the third line starts with, no matter what I try.
My current way of trying to achieve this:
from pwn import *
io = process("./testbin")
print io.recvline()
print io.recvline()
print io.recvuntil(":", timeout=1) # this get's stuck if I dont use a timeout
...
# maybe sending data here
# io.send(....)
io.close()
Do I missunderstand something about stdin and stdout? Is "Enter input:" of the third line not part of the output that I should be able to receive before making an input?
Thanks in advance
I finally figured it out.
I got the hint I needed from
https://github.com/zachriggle/pwntools-glibc-buffering/blob/master/demo.py
It seems that Ubuntu is doing lots of buffering on its own.
When manually making sure that pwnTools uses a pseudoterminal for stdin and stdout it works!
import * from pwn
pty = process.PTY
p = process(stdin=pty, stdout=pty)
You can use the clean function which is more reliable and which can be used for remote connections: https://docs.pwntools.com/en/dev/tubes.html#pwnlib.tubes.tube.tube.clean
For example:
def start():
p = remote("0.0.0.0", 4000)
return p
io = start()
io.send(b"YYYY")
io.clean()
io.send(b"ZZZ")

How can I see the entire output of a python file when run inside terminal?

Terminal automatically cut the output as it scrolled up with each iteration.
By default mac terminal will have a limited no of lines of buffer. Say 1,000.
When you run a program and the output crossed 1000 lines your lines will be lost from memory. It's like FIFO buffer queue.
Basically the answer to your question:
`Is there a way to store the output of the previously run command in a text file?` is no. Sorry.
You can re-run the program and preserve the output by redirecting it to another file. Or increase the number of lines in the buffer (Maybe make it unlimited)
You can use less to go through the output:
your_command | less
Your Enter key will take you down.
Also, press q to exit.
Or you can reroute the output to a file
In one terminal tab run the program and redirect the output to a output.log file like this.
python program.py > output.log
In another tab you can tailf on the same log file and see the output.
tailf output.log
To see the complete output open the log file in any text editor.
You can consider increasing the scrollback buffer.
Or
If you want to see the data and also run it to a file, use tee, e.g,
spark-shell | tee tmp.out

subprocess, Popen, and stdin: Seeking practical advice on automating user input to .exe

Despite my obviously beginning Python skills, I’ve got a script that pulls a line of data from a 2,000-row CSV file, reads key parameters, and outputs a buffer CSV file organized as an N-by-2 rectangle, and uses the subprocess module to call the external program POVCALLC.EXE, which takes a CSV file organized that way as input. The relevant portion of the code is shown below. I THINK that subprocess or one of its methods should allow me to interact with the external program, but am not quite sure how - or indeed whether this is the module I need.
In particular, when POVCALLC.EXE starts it first asks for the input file, which in this case is buffer.csv. It then asks for several additional parameters including the name of an output file, which come from outside the snippet below. It then starts computing results, and then ask for further user input, including several carriage returns . Obviously, I would prefer to automate this interaction for the 2,000 rows in the original CSV.
Am I on the right track with subprocess, or should I be looking elsewhere to automate this interaction with the external executable?
Many thanks in advance!
# Begin inner loop to fetch Lorenz curve data for each survey
for i in range(int(L_points_number)):
index = 3 * i
line = []
P = L_points[index]
line.append(P)
L = L_points[index + 1]
line.append(L)
with open('buffer.csv', 'a', newline='') as buffer:
writer = csv.writer(buffer, delimiter=',')
P=1
line.append(P)
L=1
line.append(L)
writer.writerow(line)
subprocess.call('povcallc.exe')
# TODO: CALL povcallc and compute results
# TODO: USE Regex to interpret results and append them to
# output file
If your program expects these arguments on the standard input (e.g. after running POVCALLC you type csv filenames into the console), you could use subprocess.Popen() [see https://docs.python.org/3/library/subprocess.html#subprocess.Popen ] with stdin redirection (stdin=PIPE), and use the returned object to send data to stdin.
It would looks something like this:
my_proc = subprocess.Popen('povcallc.exe', stdin=subprocess.PIPE)
my_proc.communicate(input="my_filename_which_is_expected_by_the_program.csv")
You can also use the tuple returned by communicate to automatically check the programs stdout and stderr (see the link to docs for more).

Python subprocess stdout to process stdin

Edit: My main question is, is there some way for a subprocess's stdout to be non-exclusively piped into the process's stdin. Non-exclusively so that the keyboard still works. Both need to go into a raw_input prompt.
Context: I'm creating a python program that allows people who've bought tickets with qr codes entry at an event. The main part of the program is a raw_input() on loop that searches through a csv for a guest's name, email address or the unique hash that is embedded in the QR codes. I am trying to use zbarcam to scan in the unique hash. This almost works:
from subprocess import Popen, PIPE
p = Popen(["/cygdrive/c/Program Files (x86)/ZBar/bin/zbarcam", "--raw"], stdout=PIPE)
That is, the QR code is scanned and the ticket hash pops up at the prompt so I can hit enter and have it search. The problem is zbarcam adds a newline so when I hit enter, it searches for a newline and returns everything in the csv. I can't find any way to strip the newline after the zbarcam output is piped to stdout (which enters into raw_input). Come to think of it, I can't even backspace or remove the newline using the keyboard. Do you know how to do that? I've done that sort of thing before, usually by copy-pasting an extra newline.
I added this line after the above ones:
sys.stdin = p.stdout
and the QR code's newline was interpretd as an "enter" and the search process started, but it just took away my ability to type in a search term. Is there some way to have stdin routed to both of those?
Is there some other way I can get user input from a keyboard and from zbarcam?
Thanks in advance! I hope I sound coherant--been a long day.
Edit: if anyone wants to bash themselves in the head with this profoundly hacked-together code, they can have a look here https://github.com/rtwolf/qr-event-entry/blob/master/pulp_entry.py

Categories