Executing ssh command in c program using popen() - c

When I try executing this using popen it returns this error but when I run this in terminal it works!
popen("ssh -n -f *.*.*.* 'sshfs -o nonempty *.*.*.*:/home/foo/bar/ /foo1/foo2/foo3'", "r");
error:
ssh_exchange_identification: Connection closed by remote host
I use public and private key to ssh without passwords and they work properly as this command run flawlessly in terminal.
I changed it to this :
popen("ssh -n -f *.*.*.* `sshfs -o nonempty *.*.*.*:/home/foo/bar/ /foo1/foo2/foo3`", "r");
It return errors too.
error :
fuse: bad mount point `/foo1/foo2/foo3': No such file or directory
Cannot fork into background without a command to execute.
I also tried escipping the internal "" this way : \" \" but it hangs!

Replace ssh with /usr/bin/ssh, do the same with other commands, like sshfs. Specify the full path of the command, /usr/sbin/foo or whatever the case may be. popen does not necessarily use the same shell you have at the command line to execute commands. Check your documentation.

Related

Windows batch redirect output to console

The summary of this question is I have a command I'm running in batch, Some.exe args but it is not outputting to the console. It does however output to a text file if used like Some.exe args > test.txt. I've tried stuff like #Some.exe args and Some.exe args > CON to get it to output to the console, but neither seems to work.
Are there any other approaches which might work?
This follows on from a previous question I asked DOORS make console the interactive window.
I'm calling a program called DOORS through a batch script. It runs a simple script, hello.dxl that looks like
cout << "Hello world"
The batch script, Run.bat looks like
"C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" -u test -pass testPass -b hello.dxl
When this is run, no output appears on the screen and there are no popup windows or anything (if hello.dxl said print("Hello World") an interactive window would pop-up, but not with cout)
If I add > test.txt to the end of the command
"C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" -u test -pass testPass -b hello.dxl > test.txt
It outputs the Hello World to test.txt successfully. Something I noticed is when using print("Hello World") there was no output sent to the test.txt file and an interactive window popped up so it looks like cout is the way to go.
So I though the output might just not be being output anywhere, so I tried adding > CON instead to try to force it to go to the console.
"C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" -u test -pass testPass -b hello.dxl > CON
But that still resulted in a blank output.
I also tried adding an #, before the command, as suggested in this Batch - redirect program output to current console, like
#"C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" -u test -pass testPass -b hello.dxl
or
#"C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" -u test -pass testPass -b hello.dxl > CON
But no luck there either
I would have tried to reproduce this issue without DOORS but I don't know what is causing it in the first place.
Edit: I'm not really looking to use > test.txt & type test.txt as that is the current workaround I am using. But ideally I don't want it outputting to a text file
Turns out this approach has limited functionality, as soon as I tried opening a module, it made the interactive window pop up and no output was visible in the interactive window or the the console window
This is not an issue with the > test.txt & type test.txt workaround
Based on #PA.'s suggestion that the program is somehow preventing output to stdout but not if it was redirected, so I wrote a small C# console app which looks like
using System;
using System.Diagnostics;
using Process process = new();
process.EnableRaisingEvents = true;
process.ErrorDataReceived += ErrOut;
process.OutputDataReceived += StdOut;
process.StartInfo.FileName = args[0].Trim();
process.StartInfo.Arguments = args[1].Trim();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit();
static void ErrOut(object sender, DataReceivedEventArgs dataReceivedEventArgs)
{
if (dataReceivedEventArgs.Data != null)
{
Console.WriteLine(dataReceivedEventArgs.Data);
}
}
static void StdOut(object sender, DataReceivedEventArgs dataReceivedEventArgs)
{
if (dataReceivedEventArgs.Data != null)
{
Console.WriteLine(dataReceivedEventArgs.Data);
}
}
I then exported this to a single exe using the command
dotnet publish /p:DebugType=None /p:DebugSymbols=false /p:PublishReadyToRun=true /p:PublishSingleFile=true /p:PublishReadyToRunShowWarnings=true /p:PublishTrimmed=false /p:IncludeNativeLibrariesForSelfExtract=true /p:IncludeAllContentForSelfExtract=true "RedirectOutput.csproj" -o "." -c release
which I added then just added the folder with that exe in to my path environment variable.
Now I can just do
RedirectOutput "C:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.exe" "-u test -pass testPass -b hello.dxl"
and I get the desired output
This is more a workaround.
The idea is to a use a pipe program in order to redirect the output of the Windows program to the console:
SomeWinProg SomeArgs 2>>&1 | SomePipeProg PipeProgArgs
As a pipe program you may use a program that passes throug everything, like:
SomeWinProg SomeArgs 2>>&1 | findstr /r "/c:.*"
If this works or not depends on the Windows program.
Concerning the timing:
There may be some trouble when you have a long time running Windows program which produces sporadic output or when the output is done always to the same line (no line feeds, only carriage returns) and you want to have the output in real time.
In these cacses Windows programs like findstr or find are a little bit weak.
On github there is an implementation of mtee thats fits better:
SomeWinProg SomeArgs 2>>&1 | mtee nul

sh: 1: /my_path/ompi-1.1/compiler/ompi: permission denied when I run my C program

I have installed a software named "OMPi" (after make, it generated two executable file ompicc and ompi, and you can use ompicc -x file to do something, and ompi will be called by ompicc).
When I run the command ompicc ~/Documents/example.c in the directory "/my_path/ompi-1.1/compiler" (ompicc is here and ompi is in the sub_path "./ompi/"), an error occurred sh: 1: /my_path/ompi-1.1/compiler/ompi: permission denied. But when I ran the same command in any other directories, the error didn't occur.
sudo chmod 777 -R ompi-1.1 is no use.
I think it may be because the sub_path "./ompi/" get the same name with file ompi. So, I created a directory named "ompi/" in home_path, and then ran the above command. To my surprise, the error didn't occur. It seems that the error only occur when I run the command in the directory: /my_path/ompi-1.1/compiler/
information in terminal
From the looks of it (I have briefly checked ompi's source code), the ompi program is expected by ompicc to be in the same directory. It worked fine after you had created /ompi/ in home directory, because you still had executable of the same name in the same directory as ompicc. It doesn't work in the directory you specified because there's only one ompi there which is a directory.
Line that does the execution in ompicc.c (the constructed command is then ran by a system() call:
sprintf(cmd, "%s%s%s \"%s.pc\" __ompi__%s%s%s%s%s%s%s %s > \"%s\"%s",
usegdb ? "gdb " : "", /* Run gdb instead of running _ompi directly */
RealOmpiName,
usegdb ? " -ex 'set args" : "", /* Pass the arguments */
/* ...further arguments here... */
To confirm that RealOmpiName is 'ompi' i followed the program and
RealOmpiName is traced back to (through external symbol OmpiName)
Makefile.am:
-DOmpiName='"_#PACKAGE_TARNAME#"' \
Which then is used like this (to install the software):
cp -f ompi $(DESTDIR)$(bindir)/_#PACKAGE_TARNAME#
cp -f ompicc $(DESTDIR)$(bindir)/#PACKAGE_TARNAME#cc
I think the installer wouldn't put the two programs together if it didn't require the two to be in the same directory in the first place.
Solution: ompi and ompicc have to be in the same folder/directory.

Use of su command in c code

I want to use a command in my c code. This command works properly when i am a superuser in terminal (using su) but does not work when I use sudo. I gathered that I can use system() in my c code as follows
system("su -c \"mycommand\"")
myCommand is a command that sends input to some device, like (echo 1 > mydevice)
I compiled my c code using gcc and run the output file. The trouble is, it wants root password from terminal when it comes to this line.
Is there a way I supply password programatically? I did it before with sudo command with -S option, but sudo command does not work for this case. If it is not possible, is there another way to deal with this?
Try this instead,
system("sudo sh -c \"mycommand\"");

Stifling "file or directory not found" messages in popen

I'm using popen to run a system script, like so:
snprintf(cmd, MAX_PATH, "/myscript -q | grep -i %s", deviceName);
FILE *res = popen(cmd, "r");
If the script is not found, the program carries on its merry way. However, a "file or directory not found" message is displayed, which seems like an error even though in my intended usage it isn't.
Is there a way to silence this message, or should I just call ls | grep -i myscript before running this line?
Assuming your /bin/sh is a POSIX shell, or a reasonably recent Bourne shell variant, you can redirect standard output within the command before executing the actual command. You only need to prepend exec 2>/dev/null ; before the command you wish to execute.
Here is how I'd personally do this:
/* Shell syntax for redirecting standard error to /dev/null, to
* silence any errors. If /bin/sh does not support this, you can
* simply replace it with an empty string.
*/
#define POPEN_STDERR_NULL "exec 2>/dev/null ;"
...
snprintf(cmd, MAX_PATH, POPEN_STDERR_NULL "/myscript -q | grep -i -e '%s'", deviceName);
FILE *res = popen(cmd, "r");
The popen() command uses /bin/sh internally to run the specified command. The above works for all /bin/sh variants I can test, including Linux and SunOS 5.10, so it should be quite portable. (In other words, dash, bash, and SunOS 5.10 sh all work fine with it.)
Since you'll need to recompile the application for any nonstandard systems, you can always edit the macro to omit the prefix. (You can easily add a test to Makefile magic to automatically omit it if necessary, if you ever find such a system.)
Note that I modified the parameter substitution in the snprintf() call. It will work for any deviceName that does not contain a single quote. Any single quotes in deviceName should be replaced with the string '"'"' before the snprintf() call.
Questions?
I'm not too sure if you can stifle the message. The error is a standard Linux error which is printed onto the standard error stream. You can keep FD '2' which is the file descriptor for Standard error. So maybe you can close this FD.
However, I must warn you that this will prevent any errors from being printed for the rest of your program.
A better way would be to do this:
snprintf(cmd, MAX_PATH, "/myscript -q | grep -i %s 2> dummyfile", deviceName);
This will redirect the error to a dummy file which you delete immediately.
So exercise caution and decide what you would like to do...
Cheers,
VSN

How to create file and put string on it using shellscript?

I want to create a file in /usr/share/applications/ and put a string on it.
What I have so far:
sudo touch /usr/share/applications/test.desktop
dentry="testing"
sudo echo $dentry >> /usr/share/applications/test.desktop
But this raise an error Permission Denied. What should I do to make it works?
You should create the file using your own pernissions, then sudo cp it into place.
The reason the second command doesn't work is that the redirection is set up by your shell, before sudo even runs. You could work around this by running sudo sh -c 'echo stuff >>file' but this is vastly more risk-prone than a simple sudo cp, and additionally has a race condition (if you run two concurrent instances of this script, they could end up writing the information twice to the file).

Resources