I'm calling system command
system("tftp -m binary 192.168.1.1 -c get myfile > /dev/null") ;
it works fine when tftp server is running but it makes my c program crashed when tftp server is off.
Is there a way to check whether the server is available or not in c source code ?
I think your problem lies not in the availability of the server, but the fact that tftp (at least on my Ubuntu box) does not support the command-line arguments you've provided. As a matter of fact, the only command-line argument that it does support is the name of the server.
However, you could try piping commands into tftp (simulating an interactive session), like so:
system( "echo -e \"binary\\nget myfile\\nquit\" | tftp 192.168.1.1" );
If the server isn't available, it'll time out after a few seconds and return control to your program.
system("echo -e \"timeout 1\\nget myfile\" | tftp 192.168.1.1");
I used timeout options instead of quit command because actual latency which makes my program watchdog reset is performing on get command execution. So quit can not prevent this.
On the otherhand I decided to call tftp command on a bash script starting my c program.
I think that calling tftp commad on a real time c program is faulty.
Many thanks Ethan .
Related
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
I have a program that relies on a psuedo terminal that uses
term = posix_openpt()
grantpt(term)
unlockpt(term)
open(term)
to open a psuedo terminal. I'll call this program psuedoTerminal.bin
I want to open psuedoTerminal.bin from a bash script, in the following fashion (or similar)
#!/bin/bash
/bin/sh -c psuedoTerminal.bin &
The problem is when my program arrives to the posix_openpt() call, the behaviour is erratic, sometimes CPU consumption arrives to 100%, but it never works. I believe ssh, telnet, etc suffer from the same problems on opening psuedo terminals from inside scripts.
How can I run this program from inside a script? Thanks for your help.
Do not understand why my code works if I take out my loop and variables while manually executing each line. First I thought my variables were wrong, but then I tested my code with the variables but no loop and it worked.
If I put back in the loop (the only thing I'm changing), I get these weird stty errors.
while read p; do
#Send file
scp random_file.txt $p:/me/folder"
#Log in
ssh $p"#myserver.txt"
#List file, extract file, append file
#Code here
#log out
exit
done <usernames.txt
I've googled this error (which is a pretty common error) ad nauseam, but none of the solutions are working. Disabling pseudo-tty allocation nor forcing pseudo-tty allocation work for me. I always get an error, no matter the option
-t -t option
tcgetattr: Inappropriate ioctl for device
-t option
Pseudo-terminal will not be allocated because stdin is not a terminal.
stty: : Invalid argument
-T option
stty: : Invalid argument
So how do I get around these stty errors and why does it stop working when I put it in a loop?
The input redirection with <usernames.txt is replacing the standard input with the file usernames.txt. Hence the terminal is no longer the input, causing these errors. One way around this is to use a file descriptor other than standard input, e.g.:
while read p <&3; do
…
done 3<usernames.txt
Another problem you have is that the commands within the loop are executed locally, not over ssh on the remote machine, so the exit will exit your local shell (after you return from ssh by manually logging out). You can put commands to execute remotely on the ssh command line (see ssh manual, or, e.g., this question), which may eliminate your need to have the terminal as standard input in the first place.
ssh while interactive drops you into a remote shell. ssh while in a script does not do that. The body of your loop after the ssh line is not happening on the remote system when scripted this way. It is happening locally.
If you want to run code on the remote machine in the context of that ssh connection then you need to write it all as the command argument to the ssh command and/or write a script on the remote machine and execute that script as the ssh command argument.
Here I have one command which is like interactive mode:
obex_test -b $BD_ADDR $CH_NUM
This command is from a script but I want to run this command through a system call in a C program.
obex_test is nothing but obex file transfer library.
Here I want to receive a file from remote device to local device through bluetooth.
This is the manual page of obex_test
Please can anybody tell me how can I put my C program in interactive mode like this command, and I want to use this command also.
I used popen(command,"r") but its not useful; it does not take input from the user.
If I used "w" mode then I don't know what happens; I directly get a message like >Unknown Command. It's the error this command gives when we give different options. So it's taken something as a write mode.
You could have two pairs of pipes (created with the pipe(2) system call); one for data from your program to obex_test's stdin and one from obex_test's stdout to your program. Then you would fork and execve... Beware of deadlocks (your program blocked on writing to obex_test stdin when its output pipe is full and blocking it), you might need to call poll(2) or select(2)...
However, as it man pages explain, "obex_test is a test application for the libopenobex library". So why don't call directly functions inside this libopenobex library, which you would link to your program?
You can use the system command. Check the manual page for more details.
For e.g. system( "obex_test -b 172.16.7.1 1234" );
This is the command I'm using:
rsync --partial --timeout=60 --rsh='/usr/bin/ssh -i /root/.ssh/id_rsa' /path/file user#host:/remote_path/
This works when I run it on the command line, but does not work when I use system() in my C program.
Correction: This call will not work after boot up, no matter how long the program runs. If the program is restarted it will work every time no matter how many times the program is run.
status = system("rsync --partial --timeout=60 --rsh='/usr/bin/ssh -i /root/.ssh/id_rsa' /path/file user#host:/remote_path/");
The return value from rsync is 12: Error in rsync protocol data stream.
Turns out that the problem was the environment variables. HOME was set to '/' on start up instead of '/user'. ssh was unable to locate the known_hosts file and therefor the auto-login failed, causing rsync to fail.