system / pipe call changes special characters in command passed for execution - c++

I wanted to use system / pipe command to execute command which has special characters. below is the sample code.
After executing the command through system / pipe, it changes the command by changing special characters.
I am surprised to see that system command is changing the text passed as command.
run(char *cmd)
{
FILE *in;
extern FILE *popen();
char buff[2048]= {0,};
if(!(in = popen(cmd, "r")))
{
exit(1);
}
while(fgets(buff, sizeof(buff), in)!=NULL)
{
printf("%s", buff);
}
pclose(in);
}
main()
{
char cmd[2048]={0,};
sprintf(cmd,"echo \"'http://1.2.3.4/files-spaces-specialchars-
ascii/%23#%23##!#!#!#%23%23$$$$$$$ASA(()
(!FreemakeAudioConverterSetup.exe'\" >>/tmp/logger 2>&1");
printf("this is CMD:[%s]\n",cmd);
system("echo "" > /tmp/logger"); /* to clear file containt */
system(cmd);
run(cmd);
}
OUTPUT
[terminal]$ ./a.out
this is CMD:[echo "'http://1.2.3.4/files-spaces-specialchars-ascii/%23#%23##!#!#!#%23$$$$$$$ASA(()(!FreemakeAudioConverterSetup.exe'" >>/tmp/logger 2>&1]
[terminal]$ cat /tmp/logger
'http://1.2.3.4/files-spaces-specialchars-ascii/%23#%23##!#!#!#%23538853885388(()(!FreemakeAudioConverterSetup.exe'
'http://1.2.3.4/files-spaces-specialchars-ascii/%23#%23##!#!#!#%23538953895389(()(!FreemakeAudioConverterSetup.exe'
[terminal]$
As shown above the original command URL is getting changed after executing through system / pipe command.
Any inputs from developers?

correcting the code, so it cleanly compiles results in:
Note: I also added a call to perror() so if the call to popen() fails the user is properly notified of what happened.
#include <stdio.h>
#include <stdlib.h>
void run(char *cmd)
{
FILE *in;
extern FILE *popen();
char buff[2048]= {'\0'};
if(!(in = popen(cmd, "r")))
{
perror( "popen for read failed" );
exit(1);
}
while(fgets(buff, sizeof(buff), in)!=NULL)
{
printf("%s", buff);
}
pclose(in);
}
int main( void )
{
char cmd[2048]={'\0'};
sprintf(cmd, "%s", "echo \"'http://1.2.3.4/files-spaces-specialchars-"
"ascii/%23#%23##!#!#!#%23%23$$$$$$$ASA(()"
"(!FreemakeAudioConverterSetup.exe'\" >>/tmp/logger 2>&1");
printf("this is CMD:[%s]\n",cmd);
system("echo "" > /tmp/logger"); /* to clear file containt */
system(cmd);
run(cmd);
}
then running that code results in:
this is CMD:[echo "'http://1.2.3.4/files-spaces-specialchars-ascii/%23#%23##!#!#!#%23%23$$$$$$$ASA(()(!FreemakeAudioConverterSetup.exe'" >>/tmp/logger 2>&1]
and cat /tmp/logger results in:
cat /tmp/logger
'http://1.2.3.4/files-spaces-specialchars-ascii/%23#%23##!#!#!#%23%23193951939519395(()(!FreemakeAudioConverterSetup.exe'
'http://1.2.3.4/files-spaces-specialchars-ascii/%23#%23##!#!#!#%23%23193961939619396(()(!FreemakeAudioConverterSetup.exe'

Related

Handing user input on terminal for application launched via exec in C++

xfreerdp asks for password if /p is not supplied as command line argument; when launched via terminal.
But when it is launched via execvp or exec, there is no prompt?
How to show this prompt? Is there a way where I can directly input password on prompt programmatically?
Same is automatically handled in Mac using swift using tasks & pipes. How to do it in C++.
Is there a way where I can directly input password on prompt programmatically?
An example (written in C) using popen() ...
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char *cmd = "xfreerdp";
char output[128] = {'\0'};
const char *arg = "myargs";
// Open process
FILE *fp = popen(cmd, "w");
if (!fp) {
fprintf(stderr, "Could not execute command ...\n");
exit(EXIT_FAILURE);
}
// Pass arguments
if (fprintf(fp, "%s", arg) < 0) {
puts("Could not pass arguments ...");
}
// Print command output (if required)
while (fgets(output, sizeof(output), fp) != NULL) {
puts(output);
}
pclose(fp);
return 0;
}

_popen() in Windows does not work interactively

I am using _popen() to create a pipe to communicate with another program which I can only execute and do not have source code access to. I have tried examples given in MSDN here (_popen example) and here (CreateProcess and CreateThread example(). Note that the code is almost the same except that for _popen I have modified it to write to pipe instead as below:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char psBuffer[128];
FILE *pPipe;
/* Run DIR so that it writes its output to a pipe. Open this
* pipe with read text attribute so that we can read it
* like a text file.
*/
if( (pPipe = _popen( "myprogram", "wt" )) == NULL )
exit( 1 );
/* Read pipe until end of file, or an error occurs. */
while(!feof( pPipe)))
{
char cmd[32]="";
while(fgets(psBuffer, 128, pPipe))
{
printf(psBuffer);
}
scanf("%s", cmd);
fprintf(pPipe,"%s",cmd);
}
/* Close pipe and print return value of pPipe. */
if (feof( pPipe))
{
printf( "\nProcess returned %d\n", _pclose( pPipe ) );
}
else
{
printf( "Error: Failed to read the pipe to the end.\n");
}
}
The output I expect to get is like:
Some Text -> from myprogram
command entered from parent
Some more Text -> from myprogram
more command from parent
..
..
Till myprogram terminates
However what I get is
Some Text -> from myprogram
command entered
and it keeps on accepting the commands eternally
Can you help here?
Thanks,
FC

shell command inside the linux daemon

I have written the daemon in C/C++ in linux.
Now I want to get the out put of ls -l (list directory) command inside daemon and write output of command to the file.
I know how to write to the file from my daemon, but,
I don't know how to execute ls -l command and get the output in buffer.
Here is the code...
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
/* Log any failures here */
ofs << "set sid : fail";
ofs.close();
exit(EXIT_FAILURE);
}
ofs << "\nchdir :" << chdir(filePath) << "\n";
/* Change the current working directory */
if ((chdir(filePath)) < 0) {
/* Log any failures here */
ofs << "chdir : fail";
ofs.close();
exit(EXIT_FAILURE);
}
/* Close out the standard file descriptors */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
while(1){
//here I want to execute the ls -l and get output of the command
}
You can use popen that executes a shell command and return the output as a pipe:
#include <stdio.h>
FILE* pipe = popen("ls -l", "r");
if (!pipe) return "ERROR";
You can also use system to execute any shell command:
#include <stdlib.h>
int system(const char *command);
To get the output of ls -l, forward it to a file ls -l >> myls.log than read that file.
system("ls -l >> myls.log");

Store output of system(file) command as a string in C

To get the type of file we can execute the command
system("file --mime-type -b filename");
The output displays in to terminal.But could not store the file type using the command
char file_type[40] = system("file --mime-type -b filename");
So how to store file type as a string using system(file) function.
See the man page of system: It does not return the output of the command executed (but an errorcode or the return value of the command).
What you want is popen. It return a FILE* which you can use to read the output of the command (see popen man page for details).
You can use popen like this:
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] )
{
FILE *fp;
char file_type[40];
fp = popen("file --mime-type -b filename", "r");
if (fp == NULL) {
printf("Failed to run command\n" );
exit -1;
}
while (fgets(file_type, sizeof(file_type), fp) != NULL) {
printf("%s", file_type);
}
pclose(fp);
return 0;
}
Hmmm the first and easiest way that comes to my mind for achieving what you want would be to redirect the output to a temp-file and then read it into a char buffer.
system("file --mime-type -b filename > tmp.txt");
after that you can use fopen and fscanf or whatever you want to read the content of the file.
Ofcourse, youl'll have the check the return value of system() before attempting to read the temp-file.

How to read the failure log message displayed when a system call failed in C++?

I have a C++ code that calls a test. I am doing a system call to execute this test. When this test fails, it will display something like this " ERROR: One or more devices of following component type(s) could not be discovered:"
I have a C++ code that runs on Linux redhat and it is capable of detecting if the system call pass or failed. But it can not capture the error message (ERROR: One or more devices of following component type(s) could not be discovered:) and append into the log file or print it.
Can someone please tell me how to capture the error message (ERROR: One or more devices of following component type(s) could not be discovered:)?
PS: I am an intern, any help would be really nice.
#include<iostream.h>
int main ()
{
int i;
if (system(NULL))
puts ("Ok");
else
exit (1);
i=system("hpsp --discover -verbose --user Admin --oapasswd password");
printf ("The value returned was: %d.\n",i);
return false;
}
Instead of using system() use popen(). This will open a pipe capturing the standard output of the test program so that your program can read it via the pipe.
Example EDITED:
#define _BSD_SOURCE 1
#define BUFFSIZE 400
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *cmd = "hpsp --discover -verbose --user Admin --oapasswd password";
char buf[BUFFSIZE];
char* searchResult;
int testPassed = 0;
FILE *ptr;
if ((ptr = popen(cmd, "r")) != NULL)
while (fgets(buf, BUFFSIZE, ptr) != NULL)
{
if ((searchResult = strstr(buf, "The test passed")) != NULL )
{
testPassed = 1;
break;
}
}
if (testPassed)
printf("yea!!\n");
else
printf("boo!!\n");
pclose(ptr);
return 0;
}
You can use dup and dup2 to backup/store the stderr file descriptor to redirect to your log file. Well, I'm guessing that errors go to stderr anyways.
Here's an example if you just want to write to a log file.
//open log file, choose whatever flags you need
int logfd = open("whateveryourlogfileis", O_APPEND);
//back up stderr file descriptor
int stderr_copy = dup(STDERR_FILENO);
//redirect stderr to your opened log file
dup2(logfd, STDERR_FILENO);
//close the original file descriptor for the log file
close(logfd);
//system call here
//restore stderr
dup2(stderr_copy, STDERR_FILENO);
//close stderr copy
close(stderr_copy);
Note: dup2 closes the target file descriptor before dup2ing to it. dup just duplicates the file descriptor and returns to you the new file descriptor.