invoking less application from GNU readline - linux

Bit support question. Apologies for that.
I have an application linked with GNU readline. The application can invoke shell commands (similar to invoking tclsh using readline wrapper). When I try to invoke the Linux less command, I get the following error:
Suspend (tty output)
I'm not an expert around issues of terminals. I've tried to google it but found no answer. Does any one know how to solve this issue?
Thanks.

You probably need to investigate the functions rl_prep_terminal() and rl_deprep_terminal() documented in the readline manual:
Function: void rl_prep_terminal(int meta_flag)
Modify the terminal settings for Readline's use, so readline() can read a single character at a time from the keyboard. The meta_flag argument should be non-zero if Readline should read eight-bit input.
Function: void rl_deprep_terminal(void)
Undo the effects of rl_prep_terminal(), leaving the terminal in the state in which it was before the most recent call to rl_prep_terminal().
The less program is likely to get confused if the terminal is already in the special mode used by the Readline library and it tries to tweak the terminal into an equivalent mode. This is a common problem for programs that work with the curses library, or other similar libraries that adjust the terminal status and run other programs that also do that.

Whilst counterintuitive it may be stopped waiting for input (some OSs and shells give Stopped/Suspended (tty output) when you might expect it to refer to (tty input)). This would fit the usual behaviour of less when it stops at the end of (what it thinks is) the screen length.
Can you use cat or head instead? or feed less some input? or look at the less man/info pages to see what options to less might suit your requirement (e.g w, z, F)?

Your readline application is making itself the controlling app for your tty.
When you invoke less from inside the application, it wants to be in control of the tty as well.
If you are trying to invoke less in your application to display a file for the user,
you want to set the new fork'd process into it's own process group before calling exec.
You can do this with setsid(). Then when less call tcsetpgrpp(), it will not get
thrown into the backgroud with SIGTTOU.
When less finishes, you'll want to restore the foregroud process group with tcsetpgrp(), as well.

Related

Respond Y dynamically to a shell program

We have a startup script for an application (Owned and developed by different team but deployments are managed by us), which will prompt Y/N to confirm starting post deployment. But the number of times it will prompt will vary, depends on changes in the release.
So the number of times it will prompt would vary from 1 to N (Might be even 100 or more than that).
We have automated the deployment and startup using Jenkins shell script jobs. But startup prompts number is hardcoded to 20 which might be more at sometime.
Could anyone please advise how number of prompts can be handled dynamically. We need to pass Y whenever there is pattern in the output "Do you really want to start".
Checked few options like expect, read. But not able to come up with a solution.
Thanks in advance!
In general, the best way to handle this is by (a) using a standard process management system, such as your distro's preferred init system; or, if that's not possible, (b) to adjust the script to run noninteractively (e.g., with a --yes or --noninteractive option).
Barring that, assuming your script reads from standard input and not the TTY, you can use the standard program yes and pipe it into the command you're running, like so:
$ yes | ./deploy
yes prints y (or its argument) over and over until it's killed, usually by SIGPIPE.
If your process is reading from /dev/tty instead of standard input, and you really can't convince the other team to come to their senses and add an appropriate option, you'll need to use expect for this.

Restricting pipes and redirects (Python3)

I have a program that takes standard input from the user and runs through the command line. Is there someway to make a program ignore pipes and redirects?
For example: python program.py < input.txt > output.txt would just act as if you put in python program.py
There is no simple way to find the terminal the user launched you with in the general case. There are some techniques you can use, but they will not always work.
You can use os.isatty() to detect whether a file (such as sys.stdin or sys.stdout) appears to be an interactive terminal session. It is possible you are hooked up to a terminal session other than the one the user used to launch your program, so this is not foolproof. Such a terminal session might even be under the control of a program rather than a human.
Under Unix, processes have a notion of a "controlling terminal." You may be able to talk to that via os.ctermid(). But the user can manipulate this value before launching your process. You also may not have a controlling terminal at all, e.g. if running as a daemon.
You can inspect the parent process and see if any of its file descriptors are hooked up to terminal sessions. Unfortunately, I'm not aware of any cross-platform way to do that. On Linux, I'd start with os.getppid() and the /proc filesystem (see proc(5)). If the parent process has exited (e.g. the user ran your_program.py & disown; exit under bash), this will not work. But in that case, there isn't much you can do anyway.

system() call in perl [duplicate]

This question already has answers here:
in perl, how do we detect a segmentation fault in an external command
(2 answers)
Closed 8 years ago.
I want to make a system() call in a perl script and, because I want to redirect stdin and stdout, I think I need to pass a single string to system() and let the shell interpret the metacharacters. However, I do not seem to be able to correctly detect when the program called via system() segfaults.
The perl system() man page at http://perldoc.perl.org/functions/system.html cautions "When system's arguments are executed indirectly by the shell, results and return codes are subject to its quirks." Should I be concerned about this?
My code for testing the return value of system() is pretty much identical to the example given on the same man page (just above the warning I mention) but in retrospect that appears to be for calling system() with a LIST.
So, I tihnk my core issue is, how do I detect how a program terminated that was called in a shell from perl's system(). Apologies if this is a repeat question but I cannot find it addressed anywhere before. FWIW I'm running the script on a Fedora distro of linux.
Many thank.
I would suggest you have a look at IPC::Open2 and IPC::Open3
What you are trying to do is a bit too complicated for system which is more or less geared up to running a command, and then capturing output.
IPC::Open2 allows you to open an exec pipe to a process, and attach your own filehandles to STDIN and STDOUT, meaning you can do bidirectional communication. (Open3 also allows STDERR).
Catching signals and errors on your attached process is a bit more complicated - the only thing you're fairly sure to get is a return code. With system, $? should be set automatically, but with IPC::Open[23] you may need to use waitpid to catch the return code.

How do I read and write repeatedly from a process in vim?

It was hard to phrase this as a question, but here is what I want to do:
I want vim to execute a process and to write to its stdin and read from its stdout file descriptors repeatedly. In other words, I want a back-and-forth dialogue between vim and another program.
I'll use cat as a simple example. If you run cat with no command-line arguments, then whatever you type on stdin is output to stdout after each newline character.
What I would like is to have a vim window which displays the most recent output of some program and to be able to write to its stdin upon certain events. So, unlike the following:
:read !cat
which waits for you to finish typing and press Ctrl-D to close cat's stdin, I want to display the output immediately after I press enter and to keep the process running so that I can type more.
Ultimately, I don't intend to be typing the input to the process; I want events (e.g. moving the cursor) to trigger vim to write specific commands to this process and display the output.
The reason I want the program to continue running instead of invoking the process once for each event is that the output to the program will be commands that generate state. If the program had to be invoked for each command, it would have to save the state to a file and read it in each time.
An alternative I am considering: writing the program to listen on a port. Then, vim invokes a command that simply opens the socket and passes the vim command to the program and returns the message from the program. This would require me writing two programs, though, which I hope is unnecessary.
What I am trying to do here is write a tool that analyses your code and provides an interactive command-line interface (e.g commands like that do things like "output a list of all the lines which set this variable). However, rather than running this program in a separate terminal or screen session, I would like vim to be able to integrate the output of this program in a window, if that is possible.
You should check out vimproc. You can use vimproc#popen3 to start the process. vimproc#popen3 returns an object(=dictionary) with a stdin member field that has a write method and a stdout member field that has a read method.
The problem is how to trigger the reading and writing. Vim is single thread, so you'll have to rely on autocmd events. Obviously you'll want to try reading whenever you write something(just in case), but you should also use the CursorHold event.
You can also use Python for IO. While it seems like you can use Python threading to trigger the reading, I would advise against it as Vim was never built for multithreading and from my experience, trying to hack multithreading into it with Python threads often causes race conditions and crashes Vim.

Take user input from the background

What I'm trying to accomplish is to have a process running in background from a Linux terminal which takes user input and does things according to that input even if the terminal window is not focused, so I can work with other GUI applications, and then when I push some pre-defined buttons, something might alter the program's state without loosing the focus of my current window. Just as simple as that (not that simple for me though).
I don't ask for an specific kind of implementation. I'm fine with anything that may work: C, C++, Java, Linux Bash script... The only requisite is that it works under Linux.
Thank you very much
Well you can have your server read a FIFO or a unix domain socket (or even a message queue). Then write a client that takes command line input and writes it to the pipe/queue from some other terminal session. With FIFOs you can just echo input from the command line itself to the pipe but FIFOs come with their own headaches. The "push the button and magic happens" is a lot trickier but maybe that was badly phrased?

Resources