我正在为学校项目编写自定义 shell,并且我需要能够通过“execv”函数运行外部命令。我需要我的命令要么成功运行并具有适当的输出,要么声明未找到该命令。这是我此时的代码(带有一些用于调试的 printf() 输出):
/* Create a child process */
pid_t pid = fork();
/* Check if the fork failed */
if (pid >= 0)
{
if (pid == 0)
{
/* This is the child process - see if we need to search for the PATH */
if( strchr( command.args[0], '/' ) == NULL )
{
/* Search the PATH for the program to run */
char fullpath[ sizeof( getenv("PATH") ) ];
strcpy( fullpath, getenv("PATH") );
/* Iterate through all the paths to find the appropriate program */
char* path;
path = strtok( fullpath, colon );
while(path != NULL)
{
char progpath[COMMAND_SIZE];
/* Try the next path */
path = strtok( NULL, colon );
strcpy(progpath, path);
strcat(progpath, "/");
strcat(progpath, command.args[0]);
/* Determine if the command exists */
struct stat st;
if(stat(progpath, &st) == 0)
{
/* File exists. Set the flag and break. */
execv( progpath, command.args );
exit(0);
}
else
{
printf("Not found!\n");
}
}
printf("%s: Command not found!\n", command.args[0]);
}
else
{
...
}
/* Exit the process */
exit(EXIT_FAILURE);
}
else
{
/* This is the parent process - wait for the child command to exit */
waitpid( pid, NULL, 0 );
printf("Done with fork!\n");
}
}
else
{
/* Could not fork! */
printf("%s: %s > Failed to fork command!\n", command.args[0], strerror(errno) );
}
这是输出:
john@myshell:/home/john/project>dir
/usr/local/sbin/dir: Not found!
/usr/local/bin/dir: Not found!
/usr/sbin/dir: Not found!
/usr/bin/dir: Not found!
/sbin/dir: Not found!
/bin/dir: Found!
makefile makefile~ myshell.c myshell.c~ myshell.x
Done with fork!
john@myshell:/home/john/project>foo
/usr/local/sbin/foo: Not found!
/usr/local/bin/foo: Not found!
/usr/sbin/foo: Not found!
/usr/bin/foo: Not found!
/sbin/foo: Not found!
/bin/foo: Not found!
/usr/games/foo: Not found!
Done with fork!
john@myshell:/home/john/project>
已知命令“dir”已被发现并正确执行。输出很棒。但是,当我使用假“foo”命令时,我希望它找不到该命令(显然没有),完成“while”循环,并执行以下“printf”命令。话虽如此,我预计在输出末尾会看到以下内容:
foo: Command not found!
我尝试使用 bool 值和整数值作为“标志”来确定是否找到该命令。然而,似乎没有任何代码在 while 循环之外运行。如果我删除“exit(0)”,“printf”命令仍然不会运行。我对为什么 while 循环之外的代码似乎根本没有运行感到困惑和困惑。我也不知道这是否是我 fork 方式的问题,或者这是否与输出缓冲区有关。
我这样做的方式是否错误,或者如果未找到命令,如何确保“未找到命令”消息始终运行一次?
最佳答案
您的代码中存在错误 - 您正在使用 strcpy()
并导致缓冲区溢出:
// Note the declaration of getenv():
char *getenv(const char *name);
因此 sizeof(getenv("PATH"))
== sizeof(char*)
,可能是 4 或 8。
/* Search the PATH for the program to run */
char fullpath[ sizeof( getenv("PATH") ) ]; // allocate fullpath[4] or [8]
strcpy(fullpath, getenv("PATH")); // overrun... copy to 4-8 char stack buffer
// UNDEFINED behavior after this - Bad Things ahead.
您可以使用malloc()
来动态分配堆上的完整路径:
char* fullpath = malloc(strlen(getenv("PATH")) + 1); // +1 for terminating NUL
strcpy(fullpath, getenv("PATH")); // OK, buffer is allocated large enough
// ... use fullpath ...
// Then when you are done, free the allocated memory.
free(fullpath);
// And as a general habit you want to clear the pointer after freeing
// the memory to prevent hard-to-debug use-after-free bugs.
fullpath = 0;
关于c - 在 C fork 中, printf() 在 while() 循环之后不执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21447517/