How to terminate the grep pipe after first match - c

Im trying to execute the following code in my C program but it seems that the -m1 switch is unable to terminate the pipe. As a result the program keeps reading the entire 16 GB file. Any help would be appreciable.
char *cmd=NULL;
cmd = malloc (200);
if (cmd != NULL) {
strcpy (cmd, "sudo hexdump -v -e '");
strcat(cmd,"\"");
strcat(cmd,"%010_ad |");
strcat(cmd,"\"");
strcat(cmd," 100000/1 ");
strcat(cmd,"\"");
strcat(cmd,"%_p");
strcat(cmd,"\"\"");
strcat(cmd,"|\\n");
strcat(cmd,"\"");
strcat(cmd,"' -s 2437150492 /run/SDdownload.dd | grep -m 1 -E -o ");
strcat(cmd,"\"");
strcat(cmd,"single_install Secure cloud storage and file sharing");
strcat(cmd,"\"");
strcat(cmd,">./files/Sync.com/installation.txt");
printf("Command -> %s\n",cmd);
system(cmd);

Related

Why is the following shell command working when executed directly in command line, but not working when executed through C program using popen/system?

The command is : ps -c -p | tr -s " " | cut -d " " -f 2,6-10,13 | grep 'R'
I am running it through adb shell. Basically, I want a list of processes (and certain parameters) which are currently in the run queue. This is working fine if I run it directly through the shell.
However, if I put it in a C program and cross-compile it to run on Android, it's not working. Only ps -c -p is working (I have checked that). But on running this ps -c -p | tr -s " " | cut -d " " -f 2,6-10,13 | grep 'R', I get the output :
usage: tr [-cds] SET1 [SET2]
Translate, squeeze, or delete characters from stdin, writing to stdout
-c/-C Take complement of SET1
-d Delete input characters coded SET1
-s Squeeze multiple output characters of SET2 into one character
tr: Needs 1 argument
usage: cut OPTION... [FILE]...
Print selected parts of lines from each FILE to standard output.
-b LIST select only these bytes from LIST.
-c LIST select only these characters from LIST.
-f LIST select only these fields.
-d DELIM use DELIM instead of TAB for field delimiter.
-s do not print lines not containing delimiters.
-n don't split multibyte characters (Ignored).
cut: Needs -fcb
I think the output of ps -c -p is not being conveyed to tr, which doesn't convey it to cut.
Can you please suggest what's the issue?
Here's the code I am using:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 128
int main(int argc,char **argv)
{
char *cmd4 = "ps -c -p | tr -s " " | cut -d " " -f 2,6-10,13 | grep 'R'";
system(cmd4);
FILE *fp;
char buf[BUFSIZE];
// Another method
if ((fp = popen(cmd4, "r")) == NULL) {
printf("Error opening pipe4!\n");
return -1;
}
while (fgets(buf, BUFSIZE, fp) != NULL) {
// Do whatever you want here...
printf("cmd 4 running!");
printf("OUTPUT: %s", buf);
}
if(pclose(fp)) {
printf("Command not found or exited with error status4\n");
return -1;
}
return 0;
}
In the shell, you're using the following command:
ps -c -p | tr -s " " | cut -d " " -f 2,6-10,13 | grep 'R'
In C, you're passing the following to system (and later to popen):
ps -c -p | tr -s | cut -d -f 2,6-10,13 | grep 'R'
See the difference? Quotes need to be escaped in C source code. Also, when you have trouble like this, be sure to output the relevant data so you can see what is actually happening instead of what you planned. A simple puts(cmd4) would have revealed this instantly.

Handling error cases with scp and sshpass

I am trying to implement command line interface command for file transfer and that will call internally
sshpass -p "password" scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -r user#remote-machine:/home/QA.txt /home/faadmin/
Here error handling is not happening properly , when I am running this command using system().if in case route not there for file transfer ,or file not found errors some time they blocking the execution of CLI command.so I have check return values after executing the above Linux command not showing other than 0 and 1.how can I get other return values?
You should use popen() because system() return value tell you if the command has been executed or not. E.G.:
#include <stdio.h>
void main(void)
{
FILE *output = NULL;
char text[2048];
char cmd[256];
sprintf(cmd, "%s", "sshpass -p \"password\" scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -r user#remote-machine:/home/QA.txt /home/faadmin/");
output = popen(cmd, "r");
while(fgets(text, 1024, output) != NULL)
printf("%s", text);
pclose(output);
}

How to execute multiple commands in system() , also using a variable

Ok so I've googled for an hour or more and I still didn't solved my issue.
I have these 3 bash commands:
find . -name "file_name" -exec du -h {} \; -> gives me the file's size
ls -l --time-style='+%d/%m/%Y' "file_name" | awk '{print $6}' -> last modiffied date
ls -l "file_name"|cut -d" " -f1 -> file's permissions
And I want to execute these 3 commands at a time using system();
Output example :
File size : ...
Last modiffied date : ...
File permissions : ...
My attempt :
char command[256];
char file_name[]={"myfile.txt"};
sprintf(command,"find . -name %s -exec du -h {} \; &&
ls -l --time-style='+%D/%m/%Y' %s | awk '{print $6}' &&
ls -l %s | cut -d' ' -f1",
file_name,file_name,file_name);
system((char*)command);
NOTES : I don't have to worry about the file's path because I'm using files from the same directory I execute my c program.
Compilation error : 'Sh: && is not expected'
You needed to add a percent sign in front of each percent sign you wanted in your command, otherwise it would be interpreted by sprintf as a print-mask introducer. Additionally, you need to add a back-slash in front of each back-slash you want in your command, otherwise it would be interpreted by sprintf as an introducer (e.g. for \n etc.). Additionally, I modified the sprintf second argument (i.e. the string)... I put ending quotes at the end of each physical line in your code, and at the beginning of the next physical line in your code.
Here is an example that may be what you are looking for (at least it compiles and runs):
#include <stdio.h>
int main(int argc, char **argv)
{
char command[256];
char file_name[] = "myfile.txt";
sprintf(command, "find . -name %s -exec du -h {} \\; && "
"ls -l --time-style='+%%D/%%m/%%Y' %s | awk '{print $6}' && "
"ls -l %s | cut -d' ' -f1",
file_name,
file_name,
file_name);
printf("command: -->%s<--\n\n\n", command);
system((char*)command);
}

Using commands of .exe files in c language

a few months back I wrote a batch (windows batch file .bat) code that fetches some .exe files and use their commands to do different things. e.g encoding audio, video etc...
Now I want the same thing but want to do it in C language.
set var = "Video"ffmpeg -i %var%.mkv -f wav -| neroAacEnc -ignorelength -lc -q 0.4 -if - -of %var%-Audio.aac
This code works fine in windows batch file (given that I have specified files in the same folder.)
But now I want to do this via C language. Well I know using
system("ffmpeg -i Video.mkv -f wav -| neroAacEnc -ignorelength -lc -q 0.4 -if - -of Video-Audio.aac");
will work for C language, but the drawback is I can't use variable while exploiting ffmpeg's and neroAacEnc's commands / parameters.
So is there anyway to get around it?
(Also, I'm gonna use other .exe files as well like x264.exe and mkvmerge.exe, so i'd appreciate it if someone could tell me how to use external .exe files parameters freely in C language.)
char *var="Video"
char cmd[512];
sprintf(cmd, "ffmpeg -i Video.mkv -f wav -| neroAacEnc -ignorelength -lc -q 0.4 -if - -of %s-Audio.aac", var);
system(cmd);
you can make more than 1 variable
char *var="Video"
char *app="ffmpeg";
char cmd[512];
sprintf(cmd, "%s -i Video.mkv -f wav -| neroAacEnc -ignorelength -lc -q 0.4 -if - -of %s-Audio.aac", app, var);
system(cmd);
Try this:
char var[50];
char command[256];
sprintf(var,"%s","Video");
sprintf(command,"ffmpeg -i %s.mkv -f wav -| neroAacEnc -ignorelength -lc -q 0.4 -if - -of %s-Audio.aac",var,var);
system(command);
Use snprintf. It is safer alternative to sprintf.
/* Construct command */
#define MAX_CMD_LEN 32
char command[MAX_CMD_LEN];
const char * param1 = "abc";
int param2 = 6;
int len = snprintf(command, MAX_CMD_LEN, "ffmpeg %s %d", param1, param2);
/* Run command if all went well */
if(len > 0 && len < MAX_CMD_LEN) {
system(command); /* Runs 'ffmpeg abc 6' */
}
else {
/* Command didn't fit our buffer */
}

C: stdout hangs linux pipes

I've written a simple I/O echoing program in C to test a problem with a bigger real program. Here, linux FD redirection doesn't work.
The echoing program (aka a.out) is:
#include <stdio.h>
int main(int argc, char **argv) {
char buff[10];
while (1) {
if (fgets(buff, 10, stdin) == NULL) break;
printf("PRINT: %s \n", buff);
}
}
From Bash, I run it as:
$ mkfifo IN OUT
$ # this is a method to keep the pipes IN and OUT opened over time
$ while :; do read; echo Read: $REPLY >&2; sleep 1; done <OUT >IN &
$ a.out >OUT <IN &
$ echo xyz >IN
and there is no output produced: the Bash while loop isn't able to read from OUT.
Let's compare this a.out with cat, which instead works as expected:
$ mkfifo IN OUT
$ while :; do read; echo Read: $REPLY >&2; sleep 1; done <OUT >IN &
$ cat >OUT <IN &
$ echo xyz >IN
Read: xyz
This last line is printed on console to stderr.
cat's output, differently from a.out's, is able to travel across OUT and reach the Bash while loop, which then prints it on console.
What's wrong with a.out?
try to add fflush(stdout) after printf(...).

Resources