9

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 !

jww
  • 97,681
  • 90
  • 411
  • 885
user7886490
  • 115
  • 1
  • 1
  • 5
  • Possible duplicate of [What are the different versions of exec used for in C and C++?](https://stackoverflow.com/q/5769734/608639), [What is the difference between the functions of the exec family of system calls like exec and execve?](https://stackoverflow.com/q/20823371/608639), [What is the difference between execl and execv?](https://stackoverflow.com/q/9123697/608639), etc. – jww Apr 18 '19 at 11:20

3 Answers3

20

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.

Bodo
  • 9,287
  • 1
  • 13
  • 29
0

Try to read the manual: https://linux.die.net/man/3/execv

Excerpt:

Description The exec() family of functions replaces the current process image with a new process image. The functions described in this manual page are front-ends for execve(2). (See the manual page for execve(2) for further details about the replacement of the current process image.)

The initial argument for these functions is the name of a file that is to be executed.

The const char *arg and subsequent ellipses in the execl(), execlp(), and execle() functions can be thought of as arg0, arg1, ..., argn. Together they describe a list of one or more pointers to null-terminated strings that represent the argument list available to the executed program. The first argument, by convention, should point to the filename associated with the file being executed. The list of arguments must be terminated by a NULL pointer, and, since these are variadic functions, this pointer must be cast (char *) NULL.

The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a NULL pointer.

The execle() and execvpe() functions allow the caller to specify the environment of the executed program via the argument envp. The envp argument is an array of pointers to null-terminated strings and must be terminated by a NULL pointer. The other functions take the environment for the new process image from the external variable environ in the calling process.

Special semantics for execlp() and execvp()

The execlp(), execvp(), and execvpe() functions duplicate the actions of the shell in searching for an executable file if the specified filename does not contain a slash (/) character. The file is sought in the colon-separated list of directory pathnames specified in the PATH environment variable. If this variable isn't defined, the path list defaults to the current directory followed by the list of directories returned by confstr(_CS_PATH). (This confstr(3) call typically returns the value "/bin:/usr/bin".)

Aganju
  • 6,295
  • 1
  • 12
  • 23
-2

In C you could use the 'system' command. This will execute what you enter as a function argument.

Here is an example:

system("ls -l");

If you want to take the output you could redirect to other source.

vladxjohn
  • 19
  • 6