理解为什么 execvp 在 execv 失败的地方工作
understanding why`execvp` works where `execv` fails
我被要求在 C 中实现一个 'mini-shell'。我决定使用 execv
但它不起作用,当我将它更改为 execvp
时它起作用了!看一下代码(动作在tokExec
函数中)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
void tokExec(char command[128])
{
// 'strtok' may look innocent, but it modifies the string, so I want a copy of the original command.
char tokString[128];
// 'strlen' is the lenghth without the null terminator.
strncpy(tokString,command,strlen(command)+1);
char* tokPtr = NULL;
char tok[] = " ";
int narg = 0;
tokPtr = strtok(tokString,tok);
char *myargs[64];
while(tokPtr != NULL)
{
printf("arg %d is: %s\n",narg,tokPtr);
myargs[narg] = tokPtr;
narg = narg + 1;
tokPtr = strtok(NULL,tok);
}
printf("Total number of arguments: %d\n",narg);
// add the final 'NULL' element.
myargs[narg] = NULL;
execvp(myargs[0],myargs);
printf("error\n");
exit(1);
}
void normal()
{
char command[128];
strcpy(command,"default[=10=]");
printf("myShellZ > ");
gets(command);
while(strcmp(command,"exit") != 0)
{
int status;
pid_t pid;
if( (pid = fork()) == 0 )
{
tokExec(command);
}
wait(&status);
printf("myShellz > ");
gets(command);
}
}
void debug()
{
// TO DO ....
int a = 3;
}
// switching between shell modes: normal or debug.
int main(int argc, char* argv[])
{
if(argc == 1)
normal();
else if(strcmp("-debug",argv[1]))
debug();
else
exit(1);
exit(0);
}
如果 tokExec
末尾的 execvp
我将使用 execv
,如果我的输入只有 ls
或 ps
等 execv
很棒,但是如果我向输入添加参数,例如:ls -l myshell.c
或 evev 只是 ls -l
或 ps aux
我得到一个 error
输出。
man
几乎没有提及这些功能之间的差异,但它声称:
The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first
argument, by convention, should point to the filename associated with the file being
executed. The array of pointers must be terminated by a null pointer.
总之,在这种情况下修复我的程序的 execv
和 execvp
之间有什么区别?我知道 execv
也适用于 bash 命令,因为如果我输入不带参数的 bash 命令,它就可以工作,并且这两个函数的签名是相同的。感谢您的帮助!
答案在手册页中。如果您阅读引用部分之后的部分,它会讨论不同之处
The execlp(), execvp(), and execvpe() functions duplicate the actions
of the
shell in searching for an executable file if the specified filename does not
contain a slash (/) character. The file is sought in the colon-separated
list of directory pathnames specified in the PATH environment variable. If
this variable isn't defined, the path list defaults to the current directory
followed by the list of directories returned by confstr(_CS_PATH). (This
confstr(3) call typically returns the value "/bin:/usr/bin".)
我被要求在 C 中实现一个 'mini-shell'。我决定使用 execv
但它不起作用,当我将它更改为 execvp
时它起作用了!看一下代码(动作在tokExec
函数中)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
void tokExec(char command[128])
{
// 'strtok' may look innocent, but it modifies the string, so I want a copy of the original command.
char tokString[128];
// 'strlen' is the lenghth without the null terminator.
strncpy(tokString,command,strlen(command)+1);
char* tokPtr = NULL;
char tok[] = " ";
int narg = 0;
tokPtr = strtok(tokString,tok);
char *myargs[64];
while(tokPtr != NULL)
{
printf("arg %d is: %s\n",narg,tokPtr);
myargs[narg] = tokPtr;
narg = narg + 1;
tokPtr = strtok(NULL,tok);
}
printf("Total number of arguments: %d\n",narg);
// add the final 'NULL' element.
myargs[narg] = NULL;
execvp(myargs[0],myargs);
printf("error\n");
exit(1);
}
void normal()
{
char command[128];
strcpy(command,"default[=10=]");
printf("myShellZ > ");
gets(command);
while(strcmp(command,"exit") != 0)
{
int status;
pid_t pid;
if( (pid = fork()) == 0 )
{
tokExec(command);
}
wait(&status);
printf("myShellz > ");
gets(command);
}
}
void debug()
{
// TO DO ....
int a = 3;
}
// switching between shell modes: normal or debug.
int main(int argc, char* argv[])
{
if(argc == 1)
normal();
else if(strcmp("-debug",argv[1]))
debug();
else
exit(1);
exit(0);
}
如果 tokExec
末尾的 execvp
我将使用 execv
,如果我的输入只有 ls
或 ps
等 execv
很棒,但是如果我向输入添加参数,例如:ls -l myshell.c
或 evev 只是 ls -l
或 ps aux
我得到一个 error
输出。
man
几乎没有提及这些功能之间的差异,但它声称:
The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a null pointer.
总之,在这种情况下修复我的程序的 execv
和 execvp
之间有什么区别?我知道 execv
也适用于 bash 命令,因为如果我输入不带参数的 bash 命令,它就可以工作,并且这两个函数的签名是相同的。感谢您的帮助!
答案在手册页中。如果您阅读引用部分之后的部分,它会讨论不同之处
The execlp(), execvp(), and execvpe() functions duplicate the actions of the shell in searching for an executable file if the specified filename does not contain a slash (/) character. The file is sought in the colon-separated list of directory pathnames specified in the PATH environment variable. If this variable isn't defined, the path list defaults to the current directory followed by the list of directories returned by confstr(_CS_PATH). (This confstr(3) call typically returns the value "/bin:/usr/bin".)