I've recently been working with the execve()
system call and I've been trying to figure out why it would print the full path of the function I called.
For example, when calling ls
with execve
:
/usr/bin/ls: cannot access 'nofile': No such file or directory
I mean, if I think about it, it's quite logical. If I call /usr/bin/ls
as filename
in execve
, this is what the pathname actually is.
But why is the ls
system call output like this:
ls: cannot access[...]
and not like mine?
I was wondering if there was any solution to find out the "name" of the program I just called, not to print the full path of the program.
As it's execve
's choice and not mine, at least I guess it is, I'm not sure about it.
Thanks.
I used of execvp
function in the following code
and built it:
#include <stdio.h>
#include <sys/types.h>
void parse(char *line, char **argv)
{
while (*line != '\0') { /* if not the end of line ....... */
while (*line == ' ' || *line == '\t' || *line == '\n')
*line++ = '\0'; /* replace white spaces with 0 */
*argv++ = line; /* save the argument position */
while (*line != '\0' && *line != ' ' &&
*line != '\t' && *line != '\n')
line++; /* skip the argument until ... */
}
*argv = '\0'; /* mark the end of argument list */
}
void execute(char **argv)
{
pid_t pid;
int status;
if ((pid = fork()) < 0) { /* fork a child process */
printf("*** ERROR: forking child process failed\n");
exit(1);
}
else if (pid == 0) { /* for the child process: */
if (execvp(*argv, argv) < 0) { /* execute the command */
printf("*** ERROR: exec failed\n");
exit(1);
}
}
else { /* for the parent: */
while (wait(&status) != pid) /* wait for completion */
;
}
}
void main(void)
{
char line[1024]; /* the input line */
char *argv[64]; /* the command line argument */
while (1) { /* repeat until done .... */
printf("Shell -> "); /* display a prompt */
gets(line); /* read in the command line */
printf("\n");
parse(line, argv); /* parse the line */
if (strcmp(argv[0], "exit") == 0) /* is it an "exit"? */
exit(0); /* exit if it is */
execute(argv); /* otherwise, execute the command */
}
}
Now, when i run the program in terminal , the result is something like this (I tried with ls
command):
msi@ubuntu:~/Desktop$ ./output
Shell -> ls
1.txt
2.jpg
Qt-Creator.run
.
.
.
It also does worked with this parameter (Full path of ls
program):
Shell -> /bin/ls
1.txt
2.jpg
Qt-Creator.run
.
.
.
I found out the issue, but as It's in an answer to BattleTested - закалённый в бо
, I figured that answering it here would be better for anyone having this issue.
Basically, to call execve
, I needed a pathname (here /usr/bin/ls
), an array of arguments (which contains the program name as first argument, not just the arguments or a NULL array if none) and the environment.
Here for ls
with the -l
should've been:
pathname: "/usr/bin/ls"
arguments: {"/usr/bin/ls", "-l", NULL};
and your environment (NULL terminated).
The thing is, execve()
will use the first argument of your arguments array
, which here is /usr/bin/ls
. Simply modifying it to the program's name, and not path, fixed it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.