Linux shell 赋值。 Execvp 无法执行命令
Linux shell assignment. Execvp failing to execute commands
我正在尝试使用 C 为 linux 创建一个简单的 shell。我不明白为什么 execvp() 一直失败。我知道 execvp 不需要通过参数传递路径。我尝试通过 运行 通过 strtok 我的命令的字符数组遵循某人的建议。
我一直收到 execvp 失败:没有这样的文件或目录。我只是传递一个简单的“ls”作为测试命令。
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXARGS 20
#define CMDPROMPT "theshell>"
#define ARGPROMPT "Next argument: "
#define prompt(n) printf("%s", (n) == 0 ? CMDPROMPT : ARGPROMPT);
int main(int argc, char* argv[])
{
char arg[MAXARGS] = {0};
int i = 0,
should_run = 1, pid, exitstatus;
while (should_run)
{
prompt(*arg);
fgets(arg, MAXARGS, stdin);
char *arg = strtok(arg, " ");
char *arg_tok[MAXARGS];
while(arg)
{
arg_tok[i++] = arg;
arg = strtok(NULL, " ");
}
pid = fork();
switch(pid)
{
case -1:
perror("Fork Failed\n");
exit(1);
case 0:
execvp(arg_tok[0], arg_tok);
perror("execvp has failed");
exit(1);
default:
while( wait(&exitstatus) != pid );
printf("Child process exited with status %d, %d\n", exitstatus>>8, exitstatus&0377);
}
}
}
您有许多问题,主要在上面的评论中详细说明。您不使用 NULL
终止 execvp()
指针列表,而是使用 arg
隐藏 arg
声明为:
char *arg = strtok(arg, " ");
然后重新声明为:
char *arg = strtok(arg, " ");
最后,您无法从最后一个指针指向的字符串中删除 '\n'
。回想一下,fgets()
读取并 包含 填充的缓冲区中的 '\n'
。因此,只需将 strtok()
的分隔符列表更改为包含 '\n'
,例如" \n"
.
总而言之,你可以做到:
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h> /* include sys/wait.h for wait() */
#define MAXARGS 20
#define CMDPROMPT "theshell> " /* add space after > */
#define ARGPROMPT "Next argument: "
#define prompt(n) printf("%s", (n) == 0 ? CMDPROMPT : ARGPROMPT);
int main (void)
{
char arg[MAXARGS] = "";
int i = 0,
should_run = 1, pid, exitstatus;
while (should_run)
{
prompt (0);
fgets (arg, MAXARGS, stdin);
char *p = strtok (arg, " \n"); /* fix shadow of arg, included \n as delim */
char *arg_tok[MAXARGS] = {NULL};
while (p) {
arg_tok[i++] = p;
p = strtok(NULL, " \n");
}
pid = fork();
switch(pid)
{
case -1:
perror("Fork Failed\n");
exit(1);
case 0:
execvp (arg_tok[0], arg_tok);
perror ("execvp has failed");
exit(1);
default:
while( wait(&exitstatus) != pid );
printf ("Child process exited with status %d, %d\n",
exitstatus>>8, exitstatus&0377);
}
}
}
(注:为wait()
增加了headersys/wait.h
)
例子Use/Output
$ ./bin/execvp_ls
theshell> ls -al fh
total 152
drwxr-xr-x 2 david david 4096 Jul 1 2018 .
drwxr-xr-x 32 david david 131072 Mar 3 15:16 ..
-rw-r--r-- 1 david david 602 Jul 1 2018 Readme_ld_reqd_opts.txt
-rw-r--r-- 1 david david 124 Jul 1 2018 conversion.c
-rw-r--r-- 1 david david 30 Jul 1 2018 conversion.h
-rw-r--r-- 1 david david 250 Jul 1 2018 convert_driver.c
Child process exited with status 0, 0
theshell> ^C
另请注意,您使用宏虽然很聪明,但通常会导致比它们解决的问题更多的问题。简单地编写要显示的提示是一种更具可读性的方法。虽然这里使用的宏在这里微不足道,但它只会随着代码长度和复杂性的增加而增加。
检查一下,如果您还有其他问题,请告诉我。
我正在尝试使用 C 为 linux 创建一个简单的 shell。我不明白为什么 execvp() 一直失败。我知道 execvp 不需要通过参数传递路径。我尝试通过 运行 通过 strtok 我的命令的字符数组遵循某人的建议。
我一直收到 execvp 失败:没有这样的文件或目录。我只是传递一个简单的“ls”作为测试命令。
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXARGS 20
#define CMDPROMPT "theshell>"
#define ARGPROMPT "Next argument: "
#define prompt(n) printf("%s", (n) == 0 ? CMDPROMPT : ARGPROMPT);
int main(int argc, char* argv[])
{
char arg[MAXARGS] = {0};
int i = 0,
should_run = 1, pid, exitstatus;
while (should_run)
{
prompt(*arg);
fgets(arg, MAXARGS, stdin);
char *arg = strtok(arg, " ");
char *arg_tok[MAXARGS];
while(arg)
{
arg_tok[i++] = arg;
arg = strtok(NULL, " ");
}
pid = fork();
switch(pid)
{
case -1:
perror("Fork Failed\n");
exit(1);
case 0:
execvp(arg_tok[0], arg_tok);
perror("execvp has failed");
exit(1);
default:
while( wait(&exitstatus) != pid );
printf("Child process exited with status %d, %d\n", exitstatus>>8, exitstatus&0377);
}
}
}
您有许多问题,主要在上面的评论中详细说明。您不使用 NULL
终止 execvp()
指针列表,而是使用 arg
隐藏 arg
声明为:
char *arg = strtok(arg, " ");
然后重新声明为:
char *arg = strtok(arg, " ");
最后,您无法从最后一个指针指向的字符串中删除 '\n'
。回想一下,fgets()
读取并 包含 填充的缓冲区中的 '\n'
。因此,只需将 strtok()
的分隔符列表更改为包含 '\n'
,例如" \n"
.
总而言之,你可以做到:
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h> /* include sys/wait.h for wait() */
#define MAXARGS 20
#define CMDPROMPT "theshell> " /* add space after > */
#define ARGPROMPT "Next argument: "
#define prompt(n) printf("%s", (n) == 0 ? CMDPROMPT : ARGPROMPT);
int main (void)
{
char arg[MAXARGS] = "";
int i = 0,
should_run = 1, pid, exitstatus;
while (should_run)
{
prompt (0);
fgets (arg, MAXARGS, stdin);
char *p = strtok (arg, " \n"); /* fix shadow of arg, included \n as delim */
char *arg_tok[MAXARGS] = {NULL};
while (p) {
arg_tok[i++] = p;
p = strtok(NULL, " \n");
}
pid = fork();
switch(pid)
{
case -1:
perror("Fork Failed\n");
exit(1);
case 0:
execvp (arg_tok[0], arg_tok);
perror ("execvp has failed");
exit(1);
default:
while( wait(&exitstatus) != pid );
printf ("Child process exited with status %d, %d\n",
exitstatus>>8, exitstatus&0377);
}
}
}
(注:为wait()
增加了headersys/wait.h
)
例子Use/Output
$ ./bin/execvp_ls
theshell> ls -al fh
total 152
drwxr-xr-x 2 david david 4096 Jul 1 2018 .
drwxr-xr-x 32 david david 131072 Mar 3 15:16 ..
-rw-r--r-- 1 david david 602 Jul 1 2018 Readme_ld_reqd_opts.txt
-rw-r--r-- 1 david david 124 Jul 1 2018 conversion.c
-rw-r--r-- 1 david david 30 Jul 1 2018 conversion.h
-rw-r--r-- 1 david david 250 Jul 1 2018 convert_driver.c
Child process exited with status 0, 0
theshell> ^C
另请注意,您使用宏虽然很聪明,但通常会导致比它们解决的问题更多的问题。简单地编写要显示的提示是一种更具可读性的方法。虽然这里使用的宏在这里微不足道,但它只会随着代码长度和复杂性的增加而增加。
检查一下,如果您还有其他问题,请告诉我。