How to enable logging in xterm - c

Is it possible to turn on logging feature by default in xterm?
Lets say for example, I have example program in c that give an output in xterm everytime i ran the program from default bash terminal in linux. And I want to save the output that shows in xterm into a file everytime the programs is run.
I'm using centos7_x86_64 fyi
Thanks.

In Windowmaker:
Hold down ctrl + left click in xterm window (on the terminal text), click on "log to file".
A cool thing to do is when you're coding, log the terminal, and then when you cat the Xterm log, you see coding in fast forward. If you wanted you could video it.
Note that there are also other menus in xterm, accessible using Ctrl+Left Click, Ctrl+Middle Click, Ctrl+Right Click.
Log file will be in the directory that you launched Xterm from, and will be in the format: Xterm.log.<hostname>.<date>.<time>.log.
This is a very good question, there's no reason to mark down a question like this.

It can be done in two ways:
Using script:
xterm -e script mylogfile -c "someCommand -i input_file -o output_file -f someArg"
Redirect to a file:
xterm -e 'someCommand --arguments 2>&1> /path/to/mylogfile'

I do essentially this with "terminal-window", mrxvt, "hcm" and "pypty".
terminal-window wraps mrxvt, just filling in some commandline options. mrxvt is a lightweight, multitabbed, nonunicode terminal emulator not dissimilar to xterm.
hcm is a GUI that makes it easy to run a shell (or other command) on a remote host. It can also start an mrxvt with remote ssh's without requiring the GUI if you prefer (using hcm-term).
pypty is a /usr/bin/script reimplementation that is written in Python. It is not significantly different from /usr/bin/script, except it gives a "dated files mode", that allows you to have one file per pseudo terminal per day. So if you leave a shell logged in overnight, you get one file per day - this tends to make it easier to find what you're looking for.
All this combines to give you pseudo terminal logging with great ease. Commands are run on remote hosts, but logged locally. Just start a "fancy terminal-window" (or use hcm-term), and everything you see on the screen plus control characters (but not nonechoed passwords) will be logged under ~/.hcm/logs/<year>/<month>/<day>/* .
Also, if you hit the shell button in the lower right of mrxvt, you get another ssh session into the same remote host, which is also logged locally (to a different file under ~/.hcm/logs/...). When I started making use of that feature, I had no idea how much I would grow to like it.
You can obtain them from http://stromberg.dnsalias.org/~strombrg/hcm/ There's a video there that shows how easy it is to set up and get started with.
BTW, fancy terminal-window sets up $PS0 or "trap DEBUG" to give you command start times and finish times. It's great for post mortems. It does this without replacing any of the usual bash startup files.
I wrote terminal-window, hcm and pypty, but I can't take credit for mrxvt. :)
HTH

Related

Is it possible to override SSH expecting password input from /dev/tty in C

I am developing a piece of software in C that needs to SSH to another machine and run commands as root.
Something that looks like this:
char* GetPasswd(void);
void run(char* apnSshCommand)
{
FILE* lphSshFD = popen(apnSshCommand,"w");
fprintf(lphSshFD,GetPasswd());
fflush(lphSshFD);
fprintf(lphSshFD,"#Command to run in shell");
fflush(lphSshFD);
}
GetPasswd() would be a callback to a gui where the user has typed in the password
I know that the above code is not possible since SSH looks to it's own /dev/tty to provide the password for authentication.
I have read posts such as this that teases an answer using ioctl() and fcntl() but does not provide one. Along with this that shows it is possible from the command line however I have not been able to translate it.
Using expect is NOT an option
Using SSH keys are NOT an option
The SSH C library is NOT an option
Using sshpass is NOT an option
Without these, the only thing that I can think of is starting a new child process and redirect/close file descriptors to control what ssh has access to.
EDIT: These restrictions come from the fact that the system I am working on is extremely old and does not contain tools such as expect, sshpass and the SSH C library as well as being subject to multiple restrictions in regards to when sshkeys can be used
This works for me:
Create a script called pwd.sh that emits the password:
#!/bin/bash
echo -n mypassword
Run ssh in a new session like this:
SSH_ASKPASS=/path/to/pwd.sh DISPLAY= setsid -w ssh root#192.168.1.10 <command>
The effect of setsid is to run ssh detached from the controlling terminal, which is what is needed for it to respect SSH_ASKPASS.
I haven't tried, but I would expect to be able to run this command from C using system().
For the record, I tested this with OpenSSH_7.2p2 on Ubuntu.
I was able to come up with a solution by looking at the source code for sshpass which I found here

How do I copy everything from my terminal to a file including the stdout and the prompt using C?

I know how to get the stdout into a file using dup/dup2 system calls, but how do I get the entire output that would be normally shown on my terminal(including the prompt that says my username along with the $ symbol and the current working directory) to a file?
Yes you can, but this may be difficult in many details (depending on your expert level). For the shell to behave normally (I would mean exactly as in a terminal), then it needs to interact with a terminal (special system object). So you need to create a program that behave like a terminal, this what pseudo-terminals devices (/dev) are intended for. Read documentation about this to implement it but roughly, your application should behave like the user so should be connected to the slave side of the pseudo-terminal, and the shell to the master side of the pseudo-terminal. Then you can easily log real inputs made by the user and catch outputs made by the shell.
Can't comment cause of low reputation.
I would say there is no way to do that inside a code in C. Instead, you could use bash for example to redirect everything to a file, and leave the code in C as it is.
In this way you have all the info you want to save: prompt, current directory, call to the program (including flags), and of course the output of the program.
Well, you can do:
-For bash prompt PS1: Echo expanded PS1 (in case you want it expanded, if not there is a simple way to do it just echong PS1)
- For executed command: https://unix.stackexchange.com/questions/169259/how-to-capture-command-line-input-into-logfile-and-execute-it-at-the-same-time
- Standard output and error output: Redirect stderr and stdout in a Bash script
And that's all you want to capture, I think.
Look up the script command in Unix systems. If you want to capture all keyboard and std in/out for a command, use the script executable. If you want to see how it's done, look up the source.

Execute any command-line shell like into execve

In case this is helpful, here's my environment: debian 8, gcc (with std = gnu99).
I am facing the following situation:
In my C program, I get a string (char* via a socket).
This string represents a bash command to execute (like 'ls ls').
This command can be any bash, as it may be complex (pipelines, lists, compound commands, coprocesses, shell function definitions ...).
I can not use system or popen to execute this command, so I use currently execve.
My concern is that I have to "filter" certain command.
For example, for the rm command, I can apply it only on the "/home/test/" directory. All other destinations is prohibited.
So I have to prevent the command "rm -r /" but also "ls ls && rm -r /".
So I have to parse the command line that is given me, to find all the command and apply filters on them.
And that's when I'm begin to be really lost.
The command can be of any complexity, so if I want to make pipelines (execve execute a command at a time) or if I want to find all commands for applying my filters, I'll have to develop parser identical to that of sh.
I do not like creating the wheel again, especially if I make it square.
So I wonder if there is a feature in the C library (or that of gnu) for that.
I have heard of wordexp, but I do not see how manage pipelines, redirection or other (in fact, this does not seem made for this) and i do not see how can I retrieve all the command inside the commande.
I read the man of sh(1) to see if I can use it to "parse" but not execute a command, but so far, I find nothing.
Do I need to code a parser from the beginning?
Thank for your reading, and I apologies for my bad english : it's not my motherlanguage (thanks google translate ...).
Your problem:
I am facing the following situation: In my C program, I get a string
(char* via a socket). This string represents a bash command to execute
(like 'ls ls'). This command can be any bash, as it may be complex
(pipelines, lists, compound commands, coprocesses, shell function
definitions ...).
How do you plan on authenticating who is at the other end of the socket connection?
You need to implement a command parser, with security considerations? Apparently to run commands remotely, as implied by "I get a string (char* via a socket)"?
The real solution:
How to set up SSH without passwords
Your aim
You want to use Linux and OpenSSH to automate your tasks. Therefore
you need an automatic login from host A / user a to Host B / user b.
You don't want to enter any passwords, because you want to call ssh
from a within a shell script.
Seriously.
That's how you solve this problem:
I receive on a socket a string that is a shell command and I have to
execute it. But before execute it, i have to ensure that there is not
a command in conflict with all the rules (like 'rm only inside this
directory, etc etc). For executing the command, I can't use system or
popen (I use execve). The rest is up to me.
Given
And that's when I'm begin to be really lost.
Because what you're being asked to do is implement security features and command parsing. Go look at the amount of code in SSH and bash.
Your OS comes with security features. SSH does authentication.
Don't try to reinvent those. You won't do it well - no one can. Look how long it's taken for bash and SSH to get where they are security-wise. (Hint: it's decades because there's literally decades of history and knowledge that were built into bash and SSH when they were first coded...)

Why does the terminal show "^[[A" "^[[B" "^[[C" "^[[D" when pressing the arrow keys in Ubuntu?

I've written a tiny program in Ansi C on Windows first, and I compiled it on Ubuntu with the built-in GCC now.
The program is simple:
read the line from console with scanf().
Analyze the string and calculate.
But something weird happens. When I try to move the cursor, it prints four characters:
pressing Up prints "^[[A"
pressing Dn prints "^[[B"
pressing Rt prints "^[[C"
pressing Lt prints "^[[D"
How can this be avoided?
Why does it print these 4 characters instead of moving the cursor?
Because that's what the keyboard actually sends to the PC (more precisely, what the terminal prints for what it actually receives from the keyboard). bash for example gets those values, deciphers them and understands that you want to move around, so it will either move the cursor (in case of left/right) or use its history to fetch previous commands (up/down). So you can't expect your program to magically support arrow keys.
However, reading from standard input from the terminal already supports left/right arrow keys (I believe, but I'm not in Linux right now to test and make sure). So my guess is that there is another issue interfering. One possible cause could be that one of your modifier keys is stuck? Perhaps ALT, CTRL or SUPER?
For those who are coming from the osx (mac) try changing the shells to bash
Terminal -> Preferences -> Shells open with -> [select] Command (complete path)
then paste
/bin/bash
This might be because the user account is created in shell. You can change it to bash by two ways.
Permament solution is -
sudo chsh -s /bin/bash ${username}
To get this solution working you will have to logout and login
Temporary solution is everytime when you login into the ubuntu server type bash and hit return.
If it's under a docker container, run /bin/bash . This helped me solve the problem.
Additionally to what Shahbaz mentioned, I realized that pressing enter (thus sending an empty command) can fix the problem. This is usually necessary after using CTRLC to cancel a command.
On MacOS Terminal for me was enough to uncheck "Scroll alternate screen" for the issue to disappear. See screenshot of the preferences below.
You can (re)bind keys. Add this at the bottom of your .profile, .zshrc or whatever shell config you have.
bindkey -e
bindkey '\e\e[C' forward-word
bindkey '\e\e[D' backward-word
i think simple way is we can just do
kill %%
because this sometimes happen because of background processes.

Recording command line input and output on linux with C

Basically I want to do a program almost like a keylogger. The thing is that I as network admin sometimes I don't remember what I did to a machine on certain case, or same times I make howto's and tutorials for linux. I want to record what have i done.
So basically the idea of this program is:
you type the name of the program, (I call it rat for the moment)
$ rat
Welcome everything from now on will be recorded
recording $ ls
file1 file2 file3
recording $ quit
Bye bye
Everything you do will go out to an xml file. Something like this
<?xml version='1.0' encoding='UTF-8' ?>
<rat>
<command>
<input>ls</input>
<output>file1 file2 file3</output>
<err><err>
</command>
</rat>
i am doing some tests with fp_in = popen( input, "w");
and system, but first with popen i cant change directories and with "system i cant properly manage the input and output.
I was also checking if there is something I can do to bash like a plugin but haven't find any information.
At some points if feels like it I should create another shell (which is way beyond my current abilities) or fork bash sh. But it should been that complicated right.
I am open to suggestion where to start.
I am rusty with C, so I am reading again a lot of basic stuff.
With the xml file, later i was thinking on making a program to store this data and/or editing this data so i can create tutials and howto.
I can think of many ways of expanding this up to using printscreen so all the stored images go to a file you can upload to a server (for the moment i am glad to store the data). It could be a usefull tool.
ps. I do know this can be use for evil things too.
There already exists the script command, which will record all input and output into the terminal, writing it into a transcript. I would recommend just using that, unless you have particular needs that it doesn't meet. Actually, the nicest version of script that I've seen has been the NetBSD version, so you may want to look into that if the Linux version doesn't meet your needs.
If you would like to write it yourself, instead of using system, I would recommend that you use fork/exec to create a single shell process, which you copy all input and output into. To get an idea of how this works, I'd recommend looking at the source code for an existing version of script.
Most shells have a script built-in which will simply record the text in- and out- from the command line. Not quite what you're looking for... To my surprise script is not a built in, which means it is a model for building what you want.
The script command does almost what you want: it simply records the text in- and out- from the command line.
If you make your prompt distinctive (so that you can reliably tell the difference between shell commands and everything else) you can post-process the output of script to achieve your goals. Alternately you can hack script to get it to emit the XML you're looking for.
You can also try approaching this from a different angle. Instead of using a regular shell, connect to the machine using ssh or telnet and run your commands that way. Many ssh/telnet clients (PuTTY, for instance) have an option to log all console input and output during the session. You should be able to post-process this log to generate whatever type of logfile that you need.
Depending on your setup, you might not even have to use a second machine (you should be able to ssh into yourself).

Resources