Check if program is being piped - c

I'm writing a program that speeds up the git push operation. Here's what it needs to do:
printf("[github-username]\n[github-password]");
I'd then use it like so:
git-autologin | git push
But I don't want there to be any chance of someone simply typing git-autologin or git-autologin > file.txt and being able to see my username and password. I know it sounds silly 'cause anyone can still automate the git commands but it's unlikely that any untrusted user will ever get on my system.
My question: How could I tell if standard output is writing to a file/terminal or if it's being piped?
Edit: The git push pipe was simply an idea, not the only reason I'm asking.
Edit: Is there any way to determine the PID or more information about the process it's being piped to?

You can detect when stdout is a terminal by using (on Linux & POSIX!) the isatty(3) function, probably as isatty(STDOUT_FILENO)
So you could guess that if isatty(STDOUT_FILENO) is false, the standard output is would be redirected or piped.
Alternatively, use fstat(2) as fstat(STDOUT_FILENO, &stdoutstat);
But you should set up ssh correctly (with credentials, STFW for any SSH tutorial!) on your system, to avoid having git asking any password.

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.

Is it possible to run a program from terminal and have it continue to run after you close the terminal?

I have written a program which I run after connecting to the box over SSH. It has some user interaction such as selecting options after being prompted, and usually I wait for the processes it carries out to finish before logging out which closes the terminal and ends the program. But now the process is quite lengthy and I don't want to wait whilst being logged in, so how could I implement a workaround for this in C please?
You can run a program in the background by following the command with "&"
wget -m www.google.com &
Or, you could use the "screen" program, that allows you to attach-deattach sessions
screen wget -m www.google.com
(PRESS CTRL+D)
screen -r (TO RE ATTACH)
http://linux.die.net/man/1/screen
The process is sent the HUP signal when the shell exits. All you have to do is install a signal handler that ignores SIGHUP.
Or just run the program using nohup.
The traditional way to do this is using the nohup(1) command:
nohup mycmd < /dev/null >& output.log &
Of course if you don't care about the output you can send it to /dev/null too, or you could take input from a file if you wanted.
Doing it this way will protect your process from a SIGHUP that would normally cause it to exit. You'll also want to redirect stdin/stdout/stderr like above, as you'll be ending your ssh session.
Syntax shown above is for bash.
you can use screen command. here is a tutorial. note you might need to install it to your systems.
There are many options :-) TIMTOWTDI… However, for your purposes, you might look into running a command-line utility such as dtach or GNU screen.
If you actually want to implement something in C, you could re-invent that wheel, but from your description of the problem, I doubt it should be necessary…
The actual C code to background a process is trivial:
//do interactive stuff...
if(fork())
exit(0);
//cool, I've been daemonized.
If you know the code will never wind up on a non-linux-or-BSD machine, you could even use daemon()
//interactive...
daemon(0, 0);
//background...

Linux: Capture output of an already running process ( in pure C! )

My situation is the following: I've got a lot of small gizmos ( pretty close to routers, not exactly but anyway that's irrelevant) ; they are running a bare-bones MIPS-based Linux distro.
To control them, one can telnet there ( thru serial port ) and issue commands to an interactive bash-like shell which then writes back some output. The shell's input and output are both attached to /dev/ttyAS0.
Now, I'd like to automate all of this, i.e. write a program that will run inside the gizmo, be a small server listening on some port, and which would pass on any command to the said shell, capture shell's output and relay it back to whoever contacted to server.
I:
1) can install (small, <500KB) programs inside the gizmo
2) can't modify the OS, startup scripts, the shell, anything
3) have root access
4) know how to write a SOAP server
5) know how to get a SOAP message, translate it to a command and inject it into /dev/ttyAS0
6) DONT KNOW how to capture the shell's reply
7) know how to, having shell's reply, translate it back to a SOAP message and reply to the original inquirer.
So basically, the problem is 6) : how to, having injected a string to /dev/ttyAS0 and thus having made the shell execute it, capture the shell's output ?
I am aware of
http://etbe.coker.com.au/2008/02/27/redirecting-output-from-a-running-process/
i.e. I know that I could change the shell's stdout if I had GDB ( or strace ) running inside the box, but I can't install it there - it's too big and anyway this approach seems too much like a hack.
So, summarizing:
How root can capture stdout of an already running process, IN PURE C, without gdb or strace, with no access to the way the process is started?
Or - almost equivalently - how to capture what's being written to a terminal, IN PURE C ?
You might want to take a look at reptyr. It will probably need some adaptation to work for your system though
Have you tried driving the serial port with a kermit script? I would probably forgo trying to insert a more clever proxy on the device and just try and drive the existing interface.
If you really want to get it on the device, you may be able to look at the source to something like screen or kermit to get a sense of how they interact with ttys.

ftp client controlled by pipe in C

I am trying to control ftp client from C program (OS X). I did fork and execve - process is started ok. The problem is with pipes - I can send command to ftp client process and get feedback from it just fine (If i send "help\n" i get back help output) but what I never get in pipe is "ftp> " prompt. Any ideas?
Ivan
Your ftp client is probably behaving differently if stdin/stdout is a terminal or something else (lots of program do, for a start the C library does buffering in a different way...) If you want to control that, search information about pseudo-terminals, that's a little too technical to be explained here. (And looks first at programs like expect, it's possible you won't have to write yours).
A program can examine stdin to find out whether it's a terminal or a pipe. In your case, the FTP program probably does that (for example to know whether it can use escape sequences to render progress bars or offer command line editing).
If you really need the prompt, you have to look into PTYs (pseudo terminals) which emulate a console.
wild guess: isn't the "ftp>" prompt written to STDERR ?

Resources