Handling colored bash prompt - regex

I have an adapter code which executes some specific commands on a Linux machine via SSH. It executes commands and handles the output of each command in a specified manner.
The issue being faced is very straightforward.
I am connecting to a Bash prompt that uses colors. Here are the details of the PS1 variable:
PS1="\[\033[1;34m\][\$(date +%H%M)][\u#\h:\w]$\[^[[0m}\]"
The code uses regex which decides a valid terminal first and then proceeds with the commands.
For example, .*\$ is considered valid
I can't seem to handle [^[[0m} properly and code is not able to identify the terminal as a valid one. If I remove it from PS1 variable, things work fine.
Can anyone please suggest what regular expressions might be entered so that the code takes it as a valid terminal?

I think the PS1 variable you provided above is broken.
I ran the following experiment in my terminal window:
[guest#localhost ~] $ export PS1="\\[\033[1;34m\\][\$(date +%H%M)][\u#\h:\w]$\\[^[[0m}\\]"
[2137][guest#localhost:~]$^[[0m}
As you can see ^[[0m} is not interpreted properly. I assume it is the end of the color in the prompt. I think it should be \\[\033[0m\\].
Here is the whole PS1 variable:
PS1="\\[\033[1;34m\\][\$(date +%H%M)][\u#\h:\w]$\\[\033[0m\\]"
After testing it you get this:
[2137][guest#localhost:~]$^[[0m}export PS1="\\[\033[1;34m\\][\$(date +%H%M)][\u#\h:\w]$\\[\033[0m\\]"
[2139][guest#localhost:~]$

Related

Open the terminal and execute commands via C programming

Does someone know how to open the terminal and execute several commands using a C program ?
I have a program in C and another sets of commands executed by the terminal. I need to combine them into one program in C.
I'm using Ubuntu 10.04.
Thanks!
Your question may be somewhat misleading.
Because you want to run all the terminal commands in the c-code, perhaps you actually have only textual input / output with these commands. If so, you probably do not need the terminal.
I use popen when the output of the (terminal) program is a text stream. It is probably the easiest to use. As an example:
...
const char* cmndStr = "ls -lsa";
FILE* pipe = popen(cmndStr, "r");
...
The popen instruction executes the command in the cmndStr, and any text written to the commands (ls -lsa) standard output, is redirected into the pipe, which is then available for your C program to read in.
popen opens a separate process (but without a terminal to work in, just the pipe)
'Fork' is another way to launch a separate process, with some control over the launched processes' std i/o, but again, I think not a terminal.
On the other hand, if your output is not a simple text stream, maybe you can get by with a output-only dedicated terminal screen to accommodate special output activity. For instance, when I work with ncurses:
I manually open a terminal in the conventional way, and in the terminal
issue the command "tty" to find out the device name, and
issue a "cd" to set the focus to the working dir.
dmoen#C5:~$ tty
/dev/pts/1
dmoen#C5:~$ cd work
dmoen#C5:~/work$
Then I start my program (in a different tty), and let the program know which device I want it to use for the special output (i.e. /dev/pts/1 ) ... I typically use command line parameters to tell my program which pts or extra terminals I want it to use, but environment variables, pipes, in/out redirection, and other choices exist.
I have not tried (lately) to launch a terminal (as suggested by smrt28), except in shell. I believe this will work, but I do not see how the output from the terminal command (ls in the example) would be delivered back to your program. popen trivially delivers a text stream.
A long time ago, I used a device called 'pty' which works like a terminal, but I don't remember how to connect it usefully.
There is a set of 'exec' commands ... see man exec. To connect them back to your program, you will probably work with files, or perhaps redirecting i/o. Too many choices to list here.
And also, maybe you can connect these commands with your c program using shell pipes.
Check "man xterm", parameter -e. Then, in C, you can:
system("xterm -e ls")

Linux keyboard scancode issues: For example, UP ARROW gives ^[[A

We've been struggling for a while now to understand the keyboard scancode behavior in Linux.
When we open a normal bash shell, the arrow keys works as expected: UP shows the previous item in the history etc. However when you spawn a process, arrows does not work as expected anymore. For example, UP prints ^[[A instead of the previous command.
To demonstrate this, do something like:
bash$ ping www.google.com
Now, press UP or DOWN etc. and you will see the wrongly mapped key codes while the process is running. However, when you terminate the process the arrow keys will work again.
We've tested it on CentOs, Ubuntu, Mac and even in different shells (bash, sh, zsh) and the same happens everywhere. I've also tried different keyboard modes using kbd_mode where we tested with RAW and XLATE modes.
The closest thing I could see while searching for answers were IPython users have experienced the same behavior when IPython was not build against readline. However, this is not related to our case as far as I can see.
We are developing a C++ Tcl based console application which uses cin and cout to communicate with, and get input from the user. We are having issues with the arrow keys when we try to access the history of previously entered commands. This is a major issue for us as 99% of people expects the arrow characters to just work.
Any ideas on how we could overcome this would be much appreciated.
You must set the terminal into raw mode to get the scan codes and handle them (that is: disable ICANON, you want the non-canonical mode). You probably also want to disable ECHO (so that it doesn't print your input on the terminal).
That is what readline or linenoise are doing. See here for some code. Esp. see the function linenoiseEnableRawMode. Some other simple sample Python code is here where I have written a simple console media player which checks for the keypresses left ("\x1b[D") and right ("\x1b[C").
The relevant calls are to tcgetattr (to get the current terminal state and modify that state struct to get into raw mode and enable some other useful behavior stuff) and tcsetattr (to set the state).
readline, libedit or linenoise are some libraries which do all that work for you and provide you with history, autocompletion, etc.
At the end, you must restore back the old state, otherwise you get the behavior you are describing in your shell.

C++ Program taking control of terminal window

When using vim in the terminal, it essentially blanks out the terminal's window and gives you a new one to start coding in, yet when you exit vim the terminal's previous output is still listed. How do you clear the terminal so that it only outputs your program's output, but returns to its normal state once the process has ended? (In linux, fedora)
At the low level, you send the terminal program a set of control characters that tell it what to do. This can be a bit too complex to to manage manually.
So instead, you might want to look at a console library like ncurses, which can manage all this complexity for you.
With respect specifically to the previous content magically appearing after the program exits, that's actually an xterm feature which vim is taking advantage of and which most modern terminals support. It's called "alternate screen" or simply "altscreen". Essentially you tell the terminal program "Ok, now switch to a completely new screen, we'll come back to the other one later".
The command to switch to the alternate screen is typically \E[?47h, while the command to switch back is \E[?47l For fun try this:
echo -e "\033[?47h"
and then to switch back:
echo -e "\033[?47l"
Or for a more more complete solution which relies a bit less on your shell to set things right (these are the sequences vim normally uses):
echo -e "\0337\033[?47h" # Save cursor position & switch to alternate screen
# do whatever
#Clear alternate screen, switch back to primary, restore cursor
echo -e "\033[2J\033[?47l\0338"
You can type "clear", or add a system command in your program to call "clear". Also, if you're not aware, you can run system commands from inside vim, so you dont have to exit and type clear. You can compile and run your programs from inside vim as well, for example ->
:!clear
:!make
:!./programName
Also, I never use this technique, but I believe you can have vim call a new terminal by using :set terminal

Launch new program using exec in new terminal

I've got a program called pgm1 which create a new process using fork.
Then in this process, I launch a new program (pgm2) using the following command:
execv( exec_path_name, argv ).
But the thing is that with this method I've got both output in the same terminal.
I've been searching for a while ans the only solution i found was this one:
Open a new terminal with a system call
Attach my pgm2 to the new terminal using this soft http://blog.nelhage.com/2011/01/reptyr-attach-a-running-process-to-a-new-terminal/comment-page-1/#comment-27264
So my question is really simple, is there a more simple way to do that ?
Thanks in advance !
PS: Distro - Ubuntu 11.10 32bit
I can think of two possible solutions:
Do The Right Thing(TM) and send your output to a file: Each process can use a different file, providing both clear separation of the output and better record-keeping. As a bonus, you are also bound to see a performance improvement - terminal output is computationally expensive, even nowadays...
Execute a terminal emulator with the proper arguments: Most terminal emulators provide a way to execute a specific program in place of the shell. For example xterm:
$ xterm top
This will launch top in an xterm instance, without a shell. Quiting top also terminates the xterm window.
If your terminal emulator of choice supports this, you can use it simply by modifying the arguments passed to execv(). Of course, in this case you will be actually executing the terminal emulator instead of your program, which will then call your own process.
Keep in mind that, depending on the terminal emulator, any open file descriptors may not be passed correctly to your program - the terminal will at least mangle the standard file descriptors.

Standard input/output in Pyclewn(GDB front end for vim)

I've just installed Pyclewn. It works and shows variables and etc. But it doesn't show my program's output and when my program wants to input something, it doesn't do anything(I can write ":C run output" and it works. but not with standard I/O.
There was something in its documentation: http://pyclewn.sourceforge.net/_static/pyclewn.html
But I didn't understand what it says.
P.S: I've done that. Now I want to map for example to run those commands. but because the "nn" in /dev/pts/nn may vary, I should manually enter the number(see it from the xterm opened). I also have another problem when I map a key to a sequence of gdb commands, it says gdb is busy, I can add ":sleep 100m" between commands and the problem will be soved. but in the documentation it says that I should enable async option. but when I run pyclewn from vim with :Pyclewn command I don't know how to enable the async option.
You should use inferior_tty.py to create a terminal to be used with the program being debugged.
Abridged summary (most relevant bits only) from the FAQ:
:Cshell setsid xterm -e inferior_tty.py &
Determine what the name of the tty to be used is from this newly spawned window, then:
:Cset inferior-tty /dev/pts/nn
Or just start pyclewn from a terminal and it will automatically grab that terminal for input and output.
E.g:
pyclewn -c "main.cc other.h other.cc"