To run /bin/ls -a in the current directory you would need:
The same as argv
passed into main()
when a C program starts except NULL
terminated, and path is the same as argv[0]
.
char* argv[] = { "/bin/ls", "-a", NULL };
execvp(argv[0], argv);
Question
I'm writing a shell in C, and I'm having trouble understanding the filepath parameter needed for execvp(filepath,argv)
.
If the user typed wanted to run ls -a
in their current directory ... let's say /home/user1
... what would be the filepath
and argv
for running ls
in said directory?
Would the filepath
be the directory for where the command will be executed from /home/user1
or would it be the command's location /bin/ls
?
Solution 2
To run /bin/ls -a in the current directory you would need:
The same as argv
passed into main()
when a C program starts except NULL
terminated, and path is the same as argv[0]
.
char* argv[] = { "/bin/ls", "-a", NULL };
execvp(argv[0], argv);
OTHER TIPS
The filepath
argument to execvp()
can take either of two forms — it contains a slash or it does not contain a slash.
The filepath
argument specifies the pathname of the executable, either an absolute name (starts with slash) or a relative name (does not start with slash, but does contain a slash). The execvp()
function makes no changes to the argument, and the program is executed (or not) assuming that the file named exists and is executable.
The filepath
arguments specifies a 'simple' name such as ls
. The excevp()
function then seeks to execute a program with the name ls
found in one of the directories listed in the $PATH
environment variable. The p
in execvp()
is for 'path', as in path lookup.
If the user types ls -a
to a shell, the normal way to execute that would be to create an array of character pointers equivalent to:
char *argv[] = { "ls", "-a", 0 };
execvp(argv[0], argv);
The execvp()
will now do the path-based analysis and attempt to execute ls
from one of the directories listed in $PATH
.
If the user types /bin/ls -a
to a shell, then the normal way to execute that would be to create an array of character pointers equivalent to:
char *argv[] = { "/bin/ls", "-a", 0 };
execvp(argv[0], argv);
The execvp()
will now execute the absolute pathname specified, because that's what the user requested (as opposed to, say, /usr/bin/ls
or /usr/local/bin/ls
).
Note that the processing is actually the same — you split the command line into words; each word becomes an element of an array of character pointers that is terminated with a null pointer, and you pass the first word to execvp()
as the 'filepath' argument, and the whole array as the second argument.
Obviously, a shell can cache the locations of the actual executables, and many shells do, so that execvp()
doesn't have to do work trying to find the program (and the shells don't call execvp()
but typically call execv()
with the absolute pathname of the executable. But that isn't necessary; it is an optimization.
Note, too, that there is nothing to stop you doing:
char *argv[] = { "/honky/tonk/toys", "-a", 0 };
execvp("ls", argv);
Now argv[0]
should be "/honky/tonk/toys"
and not ls
, for all it is the ls
executable that is run. What you find in /proc
depends on you having /proc
on your system (Mac OS X does not support it, for example), but the symlink to the binary should be a link to /bin/ls
. On Linux, you're apt to find that ps
reports the binary name (ls
), even though /proc/PID/cmdline
contains the original arguments (so argv[0]
is /honky/tonk/toys
). Whether this is good or not depends on your viewpoint, but all the world is not Linux.