execve on linux, execute from arguments - c

I need to create a program that allows the user to execute a command passed as argument using execve in linux. I'm not sure about the syntax of the execve command. I wrote the program but it doesn't work with multiple arguments and I can't figure out why.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char **argv)
{
int status;
pid_t pid;
if((pid = fork())>0)
{
///Father process
wait(&status);
printf("Process terminated with status = %d\n",status);
}
else
{
///son process
int i;
char param[100];
printf("I'm the son woth PID= %d\n",getpid());
printf("%s\n",argv[0]);
printf("%s\n",argv[1]);
printf("%s\n",argv[2]);
strcpy(param,"/bin/");
strcat(param,argv[1]);
execve(param,argv,NULL);
exit(-1);
}
return 0;
}
A command that doesn't work using this code is
cp file1.txt file2.txt
Can someone help me?

This version is corrected:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char **argv)
{
int status;
pid_t pid;
if((pid = fork())>0)
{
///Father process
wait(&status);
printf("Process terminated with status = %d\n",status);
}
else
{
///son process
int i;
char program[100];
printf("I'm the son woth PID= %d\n",getpid());
strcpy(program,argv[1]);
printf("Program: %s\n", program);
execve(program, argv+1, NULL);
exit(0);
}
return 0;
}
Example:
$ ./a.out /bin/cp a.txt b.txt
I'm the son woth PID= 1590
Program: /bin/cp
/bin/cp
a.txt
b.txt
Process terminated with status = 0
Example 2:
./a.out /bin/ls
I'm the son woth PID= 3021
Program: /bin/ls
/bin/ls
a.c a.out
Process terminated with status = 0
I've added #include <unistd.h> because I needed it.
I recommend you to do more printf in order to understand and troubleshoot.
Edit As #jonathan-leffler say, you can use execvp to be able to exec programs using PATH:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char **argv)
{
int status;
pid_t pid;
if((pid = fork())>0)
{
///Father process
wait(&status);
printf("Process terminated with status = %d\n",status);
}
else
{
///son process
int i;
char program[100];
printf("I'm the son woth PID= %d\n",getpid());
strcpy(program,argv[1]);
printf("Program: %s\n", program);
execvp(program, argv+1);
exit(0);
}
return 0;
}
Example:
▶ ./a.out ls
I'm the son woth PID= 5056
Program: ls
a.c a.out
Process terminated with status = 0

Related

How to communicate from children process(exec) with parent through pipe()?

I have these two files and i call exec.c from main.c using exec(). As far as I understand exec.c should inherit the pipe but it says there is no link pipe in exec.c. What is the problem here?
main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define die(e) \
do \
{ \
fprintf(stderr, "%s\n", e); \
exit(EXIT_FAILURE); \
} while (0);
int main(int argc, char *argv[])
{
int link[2];
pid_t pid;
char foo[4096];
if (pipe(link) == -1)
die("pipe");
if ((pid = fork()) == -1)
die("fork");
if (pid == 0)
{
dup2(link[1], STDOUT_FILENO);
close(link[0]);
close(link[1]);
execvp("./exec", argv);
die("execl");
}
else
{
close(link[1]);
int nbytes = read(link[0], foo, sizeof(foo));
printf("Output: (%.*s)\n", nbytes, foo);
wait(NULL);
}
return 0;
}
exec.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
int main(int argc, char *argv[])
{
char a;
a='A';
write(link[1],&a,sizeof(a));
return 0;
}
I am just practicing and want to output the data that is save from pipe()
What I am doing wrong, can you help me to debug?
TIA!
In the main.c program you connect the pipe through standard output of the child process.
That means the child process passes information to the parent process through its normal standard output.
From this follows that the exec.c program could be as simple as this:
#include <stdio.h>
int main(void)
{
printf("A");
}
More specifically, your exec.c Source file doesn't have any idea of the pipe, and definitely not about the variable link, and will simply fail to build.

Obtaining the status of execv without stopping the execution of the parent

Is there a way to obtain the status of a command run with execv without waiting for it with waitpid or wait?
The program I need to do reads other executable program as argument and need to print the status of this program when executed with execv exactly when the command is finished executing, but needs to keep executing after the fork instead of waiting for the program passed as argument to finish executing.
Here is what I have right now which doesn't seem to capture any status:
#define _GNU_SOURCE
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio_ext.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/shm.h>
int status;
void child_exit_handler(int signal)
{
int pid = wait(&status);
}
int main(int argc, char *argv[])
{
pid_t pid;
signal(SIGCHLD, child_exit_handler);
for (int i = 1; i < argc; i++)
{
pid = fork();
if (pid == 0)
{
char *cmd[4];
cmd[0] = "sh";
cmd[1] = "-c";
cmd[2] = argv[i];
cmd[3] = NULL;
execv("/bin/bash", cmd);
}
}
if (pid > 0)
{
// do something;
// later do something with status
}
}

I'm getting a final link error when I compile a c program

I'm writing this program:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
int main(){
int fd[2];
pid_t pid;
pipe(fd);
pid = fork();
if(pid>0)
{
while(1){
char * command = (char*)malloc(55);
printf("Command: ");
fgets(command,55,stdin);
write(fd[1],&command,55);
wait(NULL);
}
}
else if(pid)
{
char * command = (char*)malloc(55);
read(fd[0],&command,55);
printf("Child command: %s",command);
}
return 0;
}
and when I compile I'll get this error:
I can't figure out what could be. I know that I'm not using all libraries and checking for errors but i think that's not the issue here. Thanks! Have a great day!

cannot execute execl after fork

My goal is to create N process child with one process father.
I am using two files.The first is named forkn.c which contains this code:
#include <sys/types.h>
#include <wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char* argv[] )
{
int status =4;
int i=1;
int wpid;
for (int cpt=0;cpt<atoi(argv[1]);cpt++)
{
if (i>0)
{
i=fork();
if(i>0)
printf("I create process number %d \n",cpt+1);
}
}
//The father process created argv [1] son ​​process. This ensures a single father and argv [1] son ​​process
if(i==0)
{
execl("~/tpBash/tp2/argv[2]","argv[2]",(char*) NULL);
}
if (i>0)
{
for(int cpt=0;cpt<atoi(argv[1]);cpt++)
{
wait(&status) ;
}
printf("I am the father, I waited all my son processes, I finished \n");
}
}
And there is the code of trait2.c:
#include <sys/types.h>
#include <wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int status =4;
printf("I am the child process,my PID is : %d \n",getpid());
exit(status);
}
After i compile :
gcc -std=c99 forkn.c -o forkn
gcc -std=c99 trait2.c -o trait2
And then run the executable file :
./forkn 3 trait2
the first arguments is N (the number of child process to create ) and the second argument is the name of file to execute.
My problem is that the child process does not work.
Any idea please
The problem you are seeing is related to the way you're trying to do string interpolation:
execl("~/tpBash/tp2/argv[2]","argv[2]",(char*) NULL);
I suggest you try snprintf:
char buffer[ENOUGH];
snprintf(buffer, sizeof buffer, "%s/tpBash/.../...%s", home, argv[2]);
execl(buffer, argv[2]...);
Also, the second argument to execl should be argv[2] and not "argv[2]".

Terminating a c function

I want to make a function in c, that will capture video under Linux. I embedded ffmpeg command via system() in my c program, which captures video. ffmpeg terminates by pressing [q]. How can I include termination into my c program.
This function is part of a server.c program. When client requests for termination, I want video cature function to terminate. Is this possible?
#include<stdio.h>
#include <string.h>
main()
{
char command[180];
sprintf(command, "ffmpeg -f v4l2 -r 25 -s 640x480 -i /dev/video0 out.avi");
system(command);
}
As you asked sample for fork, exec, kill here is possible solution.
avconv is replacement for ffmpeg on my pc.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <sched.h>
#include <sys/wait.h>
pid_t parent_pid;
void sigquit_handler (int sig)
{
assert(sig == SIGKILL);
pid_t self = getpid();
if (parent_pid != self)
{
printf("recording done");
_exit(0);
}
}
int main()
{
int pid = 0;
int status;
pid_t child;
signal(SIGKILL, sigquit_handler);
parent_pid = getpid();
pid = fork();
if ( pid == 0)
{
execl("/usr/bin/avconv","avconv","-f","video4linux2","-r","25","-s","640x480","-i","/dev/video0","out.avi",(char*)0);
}
else if( pid > 0)
{
sleep(5);
kill(pid, SIGKILL);
child = wait(&status);
printf("child %d succesully quit\n", (int)child);
}
return 0;
}

Resources