我为uni编写了一个方法,该方法应该启动一个程序。我必须使用execve。但这是行不通的。例如,当我使用execvp而不是execve时,它可以工作并启动程序。
#include <stddef.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
pid_t run_command(char **argv, int no_fork){
extern char **environ;
pid_t pid;
if(no_fork != 0){
execve(*argv, argv, environ);
return 0;
}
else{
if((pid = fork()) < 0){
printf("Error: fork!\n");
return -1;
}
else if(pid == 0){
argv++;
printf("execve(%s)\n", *argv);
execve(*argv, argv, environ);
}
else {
wait(NULL);
}
}
return pid;
}
/*
int run_cmdline(char ** argv){
return 0;
}*/
int main(int argc, char* argv[]){
run_command(argv, 0);
return 0;
}
编译:
clang -o main shell.c
例如执行:
./ main firefox
应启动Firefox。使用execvp且不使用环境时,它可以工作,但对于execve则不行。
感谢您的帮助:)
答案 0 :(得分:2)
execve(* argv,argv,environ);
./ main firefox
execve
不搜索PATH。您必须提供可执行文件的完整路径或自己解决该路径。这种行为的参考在posix中,但我很难读懂,man execve在我看来更容易。
类似这样:
./main /usr/bin/firefox
应该有效,甚至:
./main /usr/bin/sh -c firefox
或者也许只使用execvp
即可自动神奇地获取“父级” environ
并搜索路径。还有linux扩展名execvpe
,它不在posix中,并且确实使用environ
。
答案 1 :(得分:0)
您正在使用run_command
的参数列表调用main
。由于您要运行的程序及其参数位于argv[1]
之后,因此您需要检查argc
至少为2,然后调用run_command(argv + 1, 0)
。
编辑
似乎run_command
本身会递增argv
,但是仅出于某种原因在调用execve
的两个代码路径之一中。这两个代码路径应一致地处理参数列表。就个人而言,我认为最好让调用者安排run_command
的{{1}}引用它应该运行的程序。
如果您坚持要在argv[0]
本身中递增argv
,以使其run_command
引用要运行的程序,那么您需要检查*argv
和{{ 1}}都为非空,然后再递增argv[0]
。如果调用方负责使argv[1]
的{{1}}引用要运行的程序,那么最好检查argv
是否为空。