I am writing a code that represent a new shell to Linux. One of the commands I want to support is running a process for example if I get the following line
command [arguments]
Then I want to run command
as a process until it finishes running the process.
To do so I know I need to use fork()
in order to get the child process and gets it's PID, my problem is that I don't know what is the difference between :
exec
, execvp
, execl
, execv
... and I don't know which one to use and why.
My current code :
void External_Process(char *arguments[MAX_ARG], char* command)
{
int pID;
switch(pID = fork())
{
case -1:
perror("fork failed");
break;
case 0 :
setpgrp();
//execv(command, arguments);
//execvp(command, arguments);
//execl("/bin/bash", "/bin/bash","-c",command,NULL);
printf("smash error: > bad command %s\n" , command);
exit(-1) ;
break;
default:
return ;
}
}
Thank you !
execve() is a POSIX (and UNIX systems in general) function of the family of the exec*() functions that replace the current process image. The v comes from the fact that it takes an argument argv to the vector of arguments to the program (the same way the main function of a C program may take it).
execl() System Function: In execl() system function takes the path of the executable binary file (i.e. /bin/ls) as the first and second argument. Then, the arguments (i.e. -lh, /home) that you want to pass to the executable followed by NULL. Then execl() system function runs the command and prints the output.
The last argument must be (char*)0 , or you have undefined behavior. The first argument is the path of the executable. The following arguments appear in argv of the executed program. The list of these arguments is terminated by a (char*)0 ; that's how the called function knows that the last argument has been reached.
execvp() returns a negative value if the execution fails (e.g., the request file does not exist).
Summary: In your case I would recommend to use execvp
.
To find out the differences between the exec*
functions you should read the documentation:
https://linux.die.net/man/3/exec
https://linux.die.net/man/2/execve
The difference between execl*
and execv*
is the argument passing. execl*
require a list of arguments while execv*
require a vector of arguments.
A list of arguments is useful if you know all the arguments at compile time. In your case the arguments will be entered by the user and you have to construct a vector of arguments at run time, so you should use one of the execv*
functions.
The functions with suffix p
use the PATH
environment variable to find the program (e.g. "ls"
), without this you have to specify the full path (either absolute or relative to the current directory, e.g. "/bin/ls"
). Using PATH
is what shells normally do, so this seems to be the correct choice for you.
The functions with suffix e
allow to specify the environment for the process. For simplicity I would not use this in your case.
This leads to the conclusion: execvp
Of course you could also use system
(instead of fork
/exec*
/wait*
) as mentioned in vladxjohn's answer, but in this case you would merely use a shell to interpret your command instead of implementing a basic shell.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With