I want to run shell command in C program and get stdout output.
I did it in this function:
int run_shell_cmd_nout(const char* cmd)
{
FILE *fp;
char out[4096] = {0};
char str[256] = {0};
char full_cmd[1024] = {0};
int result = 0;
// Compose full shell command
if (!sprintf(full_cmd, "/system/bin/%s", cmd))
{
printf("Failed to compose full shell command\n");
return -1;
}
// Open the command for reading.
fp = popen(full_cmd, "r");
if (fp == NULL)
{
printf("Failed to run command\n");
return -1;
}
// Read the output a line at a time - output it.
while(!feof(fp))
{
if(fgets(str, 256, fp) != NULL)
{
result = -1;
strcat(out, str);
}
}
pclose(fp);
if (result != 0)
{
printf("%s\n", out);
return -1;
}
return 0;
}
But it doesn't work with insmod.
Is there any way to intercept all outputs when invoke insmod?
Related
School project to make our own shell and facing segmentation fault issues.
Can someone help?
Edit: kind of running but "quit" doesn't trigger the exit and execvp can't run properly (says : "no such file or directory" & "or ls:invalid option -- ' "
void interactive_mode();
void batch_mode(char *path);
void parse(char *str,char *delimiter, char **args);
int execute(char **args);
int main(int argc, char *argv[]) {
if(strcmp(argv[1], "-b") == 0) {
batch_mode(argv[2]);
}
else if(strcmp(argv[1], "-i") == 0) {
interactive_mode();
}
}
I suspect the segmentation fault problem derives from the interactive and batch modes code
void interactive_mode() {
int quit_flag;
char str[512];
char *commands[128];
char *args[128];
quit_flag = 0;
while(1) {
printf("whatever> ");
if (fgets(str,512,stdin) == NULL) {
exit(0); //error reading
}
int i = 0;
parse(str,";",commands); //split the string into commands eg "ls -a ; ls -l" -> "ls -a ","ls -l"
while (commands[i]!=NULL) {
parse(commands[i]," ",args); //split commands into arguments eg "ls -l" -> "ls","-l"
i++;
quit_flag = execute(args);
}
if (quit_flag == 1)
exit(1);
}
}
Trying to read from file:
void batch_mode(char *path) {
FILE *fp;
char str[512];
char *commands[128];
char *args[128];
int res;
fp = fopen(path,"r");
if (fp == NULL) {
perror("Error opening file");
exit(4); //file not open
}
while(1) {
if (fgets(str, 512, fp) == NULL)
break;
int i = 0;
parse(str, ";", commands);
while (commands[i] != NULL) {
parse(commands[i], " ", args);
i++;
res = execute(args);
}
}
fclose(fp);
printf("whatever>Press Any Key to Continue\n");
getchar();
}
Parsing strings:
void parse(char *str, char *delimiter, char **args) {
char *pch;
int i = 0;
pch = strtok(str,delimiter);
while (pch != NULL) {
args[i] = pch;
i++;
pch = strtok(NULL, delimiter);
}
args[i] = NULL;
}
Executing with fork:
int execute(char **args) {
char path[50];
pid_t pid;
int status;
if(strcmp(args[0],"quit")==0) return 1; //exited by quit
strcpy(path,"/bin/");
strcat(path,args[0]);
if ((pid = fork()) < 0) {
perror("fork failed");
exit(2);
}
else if (pid == 0) {
if(execvp(path, args) < 0) {
perror("execvp failed");
exit(3);
}
}
else {
while (wait(&status) != pid) /* wait for completion */
;
}
}
Please help?
Have you tried to print all your variables argv, str, commands ... To make sure all is going on as expected there ? It could also help you locate in your script where you segfault. It will take you time, sorry I have no quick answer. For starterprintf("%d", __LINE__) would print the line number you are at, don't forget to add an explicit statement.
Otherwise you could use gdb. There is quite a learning curve, but it could be useful for another project.
hello guys i am trying to make a program which which copying binary files (the values) from the source to the target. but i has a mistake and i don't know how to solve that, how can i complete the code?
int main(int argc, char ** argv)
{
FILE * source, *target;
int numr, numw;
char buffer[100];
source = fopen(argv[1], "rb");
target = fopen(argv[2], "rb");
if ((source = fopen(argv[1], "rb")) == NULL)
{
printf("open read file error.\n");
return 0;
}
while (feof(source) == 0)
{
if ((numr = fread(buffer, 1, 100, source)) != 100)
{
if (ferror(target) != 0)
{
printf("read file error.\n");
return 0;
}
}
fwrite(buffer, 1, numr, target);
if ((numw = fwrite(buffer, 1, numr, target)) != numr)
{
printf("write file error.\n");
return 0;
}
}
fclose(source);
fclose(target);
return 0;
}
At first, you wont open source file twice. Just remove first or second fopen from code.
source = fopen(argv[1], "rb");
if (source == NULL)
{
printf("open read file error.\n");
return 0;
}
Also must open target file with "w" and check it for success.
target = fopen(argv[2], "a+w");
if (target == NULL)
{
fclose(source);
printf("open target file error.\n");
return 0;
}
Also you dont need to check that fread returned 100, if there is something wrong, ferror() will detect error for you.
numr = fread(buffer, 1, 100, source);
if (ferror(target) != 0)
{
printf("read file error.\n");
break;
}
Also you must use write function once
numw = fwrite(buffer, sizeof(char), numr, target);
if (numw != numr)
{
printf("write file error.\n");
break;
}
I edited your code and now it works fine...
int main(int argc, char ** argv)
{
FILE *source, *target;
int numr, numw;
char buffer[101];
source = fopen(argv[1], "rb");
if (source == NULL)
{
printf("open read file error.\n");
return 0;
}
target = fopen(argv[2], "a+w");
if (target == NULL)
{
fclose(source);
printf("open target file error.\n");
return 0;
}
while (feof(source) == 0)
{
memset(buffer, 0, sizeof(buffer));
numr = fread(buffer, 1, 100, source);
if (ferror(target) != 0)
{
printf("read file error.\n");
break;
}
numw = fwrite(buffer, sizeof(char), numr, target);
if (numw != numr)
{
printf("write file error.\n");
break;
}
}
fclose(source);
fclose(target);
return 0;
}
Is there any C function that can check whether a Linux kernel configuration option (CONFIG_AAAA option in /boot/config- file) is set?
Or I have to develop it myself.
After a long search with no result, I developed a function myself. Here is the code:
static int is_kconfig_set(const char *config) {
int ret = 0;
struct utsname utsname;
char pattern[BUFSIZ], buf[BUFSIZ];
FILE *fp = NULL;
if (uname(&utsname) == -1)
return 0;
memset(pattern, 0, sizeof(pattern));
memset(buf, 0, sizeof(buf));
sprintf(pattern, "%s=y", config);
sprintf(buf, "/boot/config-%s", utsname.release);
fp = fopen(buf, "r");
if (fp == NULL)
return 0;
while(fgets(buf, sizeof(buf), fp) != NULL) {
if (strncmp(buf, pattern, strlen(pattern)) == 0) {
ret = 1;
break;
}
}
fclose(fp);
return ret;
}
To check whether CONFIG_CPU_FREQ is set:
if (is_kconfig_set("CONFIG_CPU_FREQ"))
return 1;
return 0;
The only way I can think is to create your own following the approach in kernel/configs.c (this is the code that creates /proc/config.gz).
I'd like to write a program that compares two files and writes every byte in file one that is different from file two into a third file. I want to compare the files byte by byte and write any differing single bytes to the third file. I'm not very familiar with file I/O. Can someone give me an example program that accomplishes this task?
This is what I have so far:
int main(int argc, char *argv[]) {
int file1, file2, file1size, file2size;
// int difference1, difference2;
char buf;
if (argc != 3){
fprintf(stderr, "Usage %s <file1> <file2>", argv[0]);
exit(1);
}
if ((file1 = open(argv[1], 0400)) < 0) { //read permission for user on file source
fprintf(stderr, "Can't open source");
exit(1);
}
if ((file2 = open(argv[2], 0400)) < 0) { //read permission for user on file source
fprintf(stderr, "Can't open source");
exit(1);
}
file1size = lseek(file1, (off_t) 0, SEEK_END);
printf("File 1's size is %d\n", file1size);
file2size = lseek(file2, (off_t) 0, SEEK_END);
printf("File 2's size is %d\n", file2size);
}
I'm not sure how to compare file1 and file2's bytes and then write the differences to another file.
This is close to what you are looking for.
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *file1 = fopen(argv[1], "r");
FILE *file2 = fopen(argv[2], "r");
int i;
for(i = 0; !feof(file1) || !feof(file2); i++) {
int byte1 = getc(file1);
int byte2 = getc(file2);
if(byte1 != byte2) {
printf("%d %d %d\n", i, byte1, byte2);
}
}
return 0;
}
It takes the two files as command line arguments and compares the two byte-by-byte. If two bytes are different, it printf the character #, and the ASCII values of the two characters. -1 means EOF was already reached.
You'll have to (understand and) adapt this to the output format you want. (I'm assuming this is homework.)
feof tests for end-of-file.
getc gets the next character (byte) from the file. It is -1 if the end of the file has been reached.
And you seem already to know what printf does.
This does what you want, compiles, and runs,
#include <stdio.h>
int main(int argc, char *argv[])
{
int offset;
int argi=1;
int ch1, ch2;
FILE *fh1, *fh2, *fh3=stdout;
FILE *fh4=stdout;
if( argc<3 ) {
printf("usage: diff <file> <file> { <outfile> }\n"); return(1);
}
if(argi<argc) {
if(!(fh1 = fopen(argv[argi], "r"))) {
printf("cannot open %s\n",argv[argi]); return(2);
}
}
if(++argi<argc) {
if(!(fh2 = fopen(argv[argi], "r"))) {
printf("cannot open %s\n",argv[argi]); return(3);
}
}
if(++argi<argc) {
if(!(fh3 = fopen(argv[argi], "w+"))) {
printf("cannot open %s\n",argv[argi]); return(4);
}
}
if(++argi<argc) {
//duplicate output to a second file?
if(!(fh4 = fopen(argv[argi], "r"))) {
printf("cannot open %s\n",argv[argi]); return(3);
}
}
for(offset = 0; (!feof(fh1)) && (!feof(fh2)); offset++)
{
ch1=ch2='-';
if(!feof(fh1)) ch1 = getc(fh1);
if(!feof(fh2)) ch2 = getc(fh2);
if(ch1 != ch2) {
fprintf(fh3,"%d:%c %c\n", offset, ch1, ch2);
//additional file here
}
else {
fprintf(fh3,"%c\n", ch1);
//additional file here
}
}
return 0;
}
More typically, you would read entire lines using fgets, and strcmp to compare the lines. Here is how,
char str1[1024], str2[1024];
...
for(offset = 0; (!feof(fh1)) && (!feof(fh2)); offset++)
{
strcpy(str1,"-");strcpy(str2,"-");
if(!feof(fh1)) fgets(str1,sizeof(str1),fh1);
if(!feof(fh2)) fgets(str2,sizeof(str1),fh2);
if(strcmp(str1,str2)!=0)
fprintf(fh3,"%d:%s %s", offset, str1, str2);
else
fprintf(fh3,"%c", str1);
}
The loop was supposed to break but it keeps stuck on the fgets. process_P1 talks to inputHandler through a pipe. The problem is that inputHandler doesn't realize when process_P1 stops writing...the 'lalala' printf is never reached.
void process_P1(char *argv[], int fd[2], pid_t child)
{
int bytes = 0;
static char bufferIn[BUFFER_SIZE];
static char bufferOut[BUFFER_SIZE];
char line[BUFFER_SIZE];
// close reading end of pipe
close(fd[0]);
FILE *in = fopen(getInput(argv), "r");
FILE *out = fdopen(fd[1], "w");
if (in == NULL) {
sys_err("fopen(r) error (P1)");
}
int ret = setvbuf(in, bufferIn, _IOLBF, BUFFER_SIZE);
if (ret != 0) {
sys_err("setvbuf error (P1)");
}
if (out == NULL) {
sys_err("fdopen(w) error (P1)");
}
ret = setvbuf(out, bufferOut, _IOLBF, BUFFER_SIZE);
if (ret != 0) {
sys_err("setvbuf error (P1)");
}
while (fgets(line, BUFFER_SIZE, in) != NULL)
{
fprintf(out, "%s", line);
bytes += count(line) * sizeof(char);
}
// alert P2 to stop reading
//fprintf(out, "%s", STOP);
fclose(in);
fflush(out);
fclose(out);
printf("P1: file %s, bytes %d\n", getInput(argv), bytes);
// wait P2 ends
if (waitpid(child, NULL, 0) < 0) {
sys_err("waitpid error (P1)");
}
}
void *inputHandler(void *args)
{
int ret;
static char bufferIn[BUFFER_SIZE];
char line[BUFFER_SIZE];
struct node *iterator;
int *fd = (int*)args;
close(fd[1]);
FILE *in = fdopen(fd[0], "r");
if (in == NULL) {
sys_err("fdopen(r) error (P2)");
}
ret = setvbuf(in, bufferIn, _IOLBF, BUFFER_SIZE);
if (ret != 0) {
sys_err("setvbuf(in) erro (P2)");
}
while (fgets(line, BUFFER_SIZE, in) != NULL)
{
// printf("%s", line);
iterator = firstArg;
while (iterator->next != NULL)
{
ret = sem_wait(&(iterator->sem));
if (ret == 0) {
strcat(iterator->buffer, line);
} else {
sys_err("sem_wait error");
}
ret = sem_post(&(iterator->sem));
if (ret != 0) {
sys_err("sem_post error");
}
iterator = iterator->next;
}
line[0] = '\0';
}
printf("lalala\n");
iterator = firstArg;
while (iterator->next != NULL)
{
ret = sem_wait(&(iterator->sem));
if (ret != 0) {
sys_err("sem_wait error");
}
iterator->shouldStop = 1;
ret = sem_post(&(iterator->sem));
if (ret != 0) {
sys_err("sem_post error");
}
iterator = iterator->next;
}
fclose(in);
return NULL;
}
The problem is probably not in the code you show. Since you mention a pipe, your problem is probably in the plumbing related to that — and most likely, you did a dup2() on one end of the pipe to make it into standard input or standard output, but you forgot to close the file descriptor that you duplicated, or you forgot to close the other end. The fgets() won't terminate until there's no process that could write to the pipe that it is reading from. If the process that is reading still has the write end of the pipe open, it will stay stuck in the read, waiting for it to write something.
So, look hard at your piping code. Make sure you've closed both the values returned by pipe() after you've duplicated one end to standard input or standard output.