Execvp linux:试图让我的 shell 在 C 中工作
Execvp linux: trying to make my shell work in C
我正在努力使shell变得简单,但在特定条件下,我必须使用以下结构:
typedef struct cmd_struct{
char cmd[80];
char args[10][80];
int nargs;
} cmd_type;
在 cmd 中,我将在 args.
中保存主要命令和参数
然后我从文件中读取不同的命令,并将它们保存到 cmd_type 的数组中。我的程序还是假的shell,要求一个数字,应该从这个数组中取出它。
我执行命令的函数如下所示:
void execCmd(cmd_type* cmds_arg, int idxCmd){
pid_t pid;
printf("Father: my pid is %d\n", getpid());
char* buff;
pid = fork();
if (pid == 0) {
printf("Child process: My pid is %d\n", getpid());
printf("-------------- Child doing exec: %s\n", cmds_arg[idxCmd].cmd);
execvp(cmds_arg[idxCmd].cmd,&cmds_arg[idxCmd].args);
_exit(2);
_exit(1);
}
printf("Father: Gonna wait for Child\n");
int status;
wait(&status);
printf("-------------- Father: Child finished\n");
// WIFEXITED, WEXITSTATUS Macro of the gnu lib POSIX standard to recover end status
if ( WIFEXITED(status) ) {
const int es = WEXITSTATUS(status);
printf("Father: Child Complete with exit status %d\n", es);
if(es == 1) printf("Father: Child didn't execute any command\n");
else if(es == 2) printf("Father: Child command was not found\n");
}
}
如您所见,当我调用 execvp() 系统调用时,我做错了。第一个论点我认为是对的,第二个论点完全错了。
首先,我有一个转换问题,第二个问题是数组应该包含“main command”、“arg1”、“arg2”……而我的只有参数。我错了吗?
有没有办法使用sscanf()之类的服务添加“主命令”?最重要的是,我有没有机会让它以这种方式工作?
使用 char args[10][80];
,execvp(cmds_arg[idxCmd].cmd,&cmds_arg[idxCmd].args);
将不起作用(甚至无法编译),因为 execvp 需要一个 const char*
指针每个参数,你的 .args
没有任何指针。
类似这样的方法可能有效:
const char *p[11]; /* Contains up to 10 pointers + trailing NULL. */
cmd_type *this_cmd = &cmds_arg[idxCmd];
for (int i = 0; i < this_cmd->nargs; ++i) {
p[i] = &this_cmd->args[i];
}
p[this_cmd->nargs] = NULL;
execvp(this_cmd->cmd, p);
本着@pts 的回答精神,您可以在动态分配的 table:
中复制 execvp() 的参数
void execCmd(cmd_type* cmds_arg, int idxCmd){
pid_t pid;
printf("Father: my pid is %d\n", getpid());
char* buff;
pid = fork();
if (pid == 0) {
int i;
char **args = (char **)malloc((1 + cmds_arg[idxCmd].nargs + 1) * sizeof(char *));
args[0] = cmds_arg[idxCmd].cmd;
for (i = 1; i < (cmds_arg[idxCmd].nargs + 1); i ++) {
args[i] = cmds_arg[idxCmd].args[i - 1];
}
args[i] = NULL;
printf("Child process: My pid is %d\n", getpid());
printf("-------------- Child doing exec: %s\n", cmds_arg[idxCmd].cmd);
execvp(cmds_arg[idxCmd].cmd, args);
_exit(2);
}
printf("Father: Gonna wait for Child\n");
int status;
wait(&status);
printf("-------------- Father: Child finished\n");
// WIFEXITED, WEXITSTATUS Macro of the gnu lib POSIX standard to recover end status
if ( WIFEXITED(status) ) {
const int es = WEXITSTATUS(status);
printf("Father: Child Complete with exit status %d\n", es);
if(es == 1) printf("Father: Child didn't execute any command\n");
else if(es == 2) printf("Father: Child command was not found\n");
}
}
我正在努力使shell变得简单,但在特定条件下,我必须使用以下结构:
typedef struct cmd_struct{
char cmd[80];
char args[10][80];
int nargs;
} cmd_type;
在 cmd 中,我将在 args.
中保存主要命令和参数然后我从文件中读取不同的命令,并将它们保存到 cmd_type 的数组中。我的程序还是假的shell,要求一个数字,应该从这个数组中取出它。
我执行命令的函数如下所示:
void execCmd(cmd_type* cmds_arg, int idxCmd){
pid_t pid;
printf("Father: my pid is %d\n", getpid());
char* buff;
pid = fork();
if (pid == 0) {
printf("Child process: My pid is %d\n", getpid());
printf("-------------- Child doing exec: %s\n", cmds_arg[idxCmd].cmd);
execvp(cmds_arg[idxCmd].cmd,&cmds_arg[idxCmd].args);
_exit(2);
_exit(1);
}
printf("Father: Gonna wait for Child\n");
int status;
wait(&status);
printf("-------------- Father: Child finished\n");
// WIFEXITED, WEXITSTATUS Macro of the gnu lib POSIX standard to recover end status
if ( WIFEXITED(status) ) {
const int es = WEXITSTATUS(status);
printf("Father: Child Complete with exit status %d\n", es);
if(es == 1) printf("Father: Child didn't execute any command\n");
else if(es == 2) printf("Father: Child command was not found\n");
}
}
如您所见,当我调用 execvp() 系统调用时,我做错了。第一个论点我认为是对的,第二个论点完全错了。
首先,我有一个转换问题,第二个问题是数组应该包含“main command”、“arg1”、“arg2”……而我的只有参数。我错了吗?
有没有办法使用sscanf()之类的服务添加“主命令”?最重要的是,我有没有机会让它以这种方式工作?
使用 char args[10][80];
,execvp(cmds_arg[idxCmd].cmd,&cmds_arg[idxCmd].args);
将不起作用(甚至无法编译),因为 execvp 需要一个 const char*
指针每个参数,你的 .args
没有任何指针。
类似这样的方法可能有效:
const char *p[11]; /* Contains up to 10 pointers + trailing NULL. */
cmd_type *this_cmd = &cmds_arg[idxCmd];
for (int i = 0; i < this_cmd->nargs; ++i) {
p[i] = &this_cmd->args[i];
}
p[this_cmd->nargs] = NULL;
execvp(this_cmd->cmd, p);
本着@pts 的回答精神,您可以在动态分配的 table:
中复制 execvp() 的参数void execCmd(cmd_type* cmds_arg, int idxCmd){
pid_t pid;
printf("Father: my pid is %d\n", getpid());
char* buff;
pid = fork();
if (pid == 0) {
int i;
char **args = (char **)malloc((1 + cmds_arg[idxCmd].nargs + 1) * sizeof(char *));
args[0] = cmds_arg[idxCmd].cmd;
for (i = 1; i < (cmds_arg[idxCmd].nargs + 1); i ++) {
args[i] = cmds_arg[idxCmd].args[i - 1];
}
args[i] = NULL;
printf("Child process: My pid is %d\n", getpid());
printf("-------------- Child doing exec: %s\n", cmds_arg[idxCmd].cmd);
execvp(cmds_arg[idxCmd].cmd, args);
_exit(2);
}
printf("Father: Gonna wait for Child\n");
int status;
wait(&status);
printf("-------------- Father: Child finished\n");
// WIFEXITED, WEXITSTATUS Macro of the gnu lib POSIX standard to recover end status
if ( WIFEXITED(status) ) {
const int es = WEXITSTATUS(status);
printf("Father: Child Complete with exit status %d\n", es);
if(es == 1) printf("Father: Child didn't execute any command\n");
else if(es == 2) printf("Father: Child command was not found\n");
}
}