这基本上应该执行用户输入的linux shell命令并调用execvp 对于我的测试功能,为什么输入命令时就像' ls -l>为sample.txt 命令不仅不会执行,而且也不会创建文件。
但是,如果我在没有重定向的情况下运行命令,它可以正常工作。
在附加了文件名的运行失败之后,shell也完全坏了,甚至以前工作的普通命令都不起作用。
似乎ls -l有时会破坏下一个输入命令。然后它变得无法找到ls或任何其他命令。
编辑:在任何失败的命令之后,它将无法完成任何以前正在运行的命令。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <vector>
#include <algorithm>
#include <limits>
void testFunction(int num, char **argv, char **fname)
{
std::cout << "vvv testFunctionBegin vvv" << std::endl;
int status;
int fd;
if (fork() != 0)
{
std::cout << "fork() != 0" << std::endl;
waitpid(-1, &status, 0);
}
else
{
std::cout << "fork() == 0" << std::endl;
/*
if (isalnum(*fname[0]) || ispunct(*fname[0]))
{
std::cout << "File has "<< *fname[0] << std::endl;
fd = open(fname[0], O_WRONLY, O_APPEND, O_CREAT);
std::cout << "fd = " << fd << std::endl;
std::cout << "fname = " << fname[1] << std::endl;
perror("open");
dup2(fd, 1);
close(fd);
}
*/
std::cout << "argv[0] = " << *argv[0] << std::endl;
execvp(argv[0], argv);
}
}
std::vector<std::string> processString(std::string userInput)
{
int j = 0;
std::vector<std::string> subStrs;
for (int i = 0; i < userInput.size(); i++)
{
bool sameSeq = false;
if (isalnum(userInput[i]) || ispunct(userInput[i]))
{
subStrs.resize(subStrs.size() + 1);
while (isalnum(userInput[i]) || ispunct(userInput[i]))
{
subStrs[j].push_back(userInput[i]);
sameSeq = true;
//std::cout << "userInput[" << i << "] = " << userInput[i]
// << " --> " << "subStrs[" << j << "] = "
// << subStrs[j] << std::endl;
i++;
}
if (sameSeq)
{
subStrs[j].push_back('\0');
j++;
}
}
}
return subStrs;
}
int main(int argc, char **argv)
{
std::string userInput;
std::string readySym = "$ ";
std::vector<std::string> subStrs(1, "");
std::vector<char*> cmdFlgs;
std::vector<char*> fileName;
while (true)
{
std::cout << readySym;
getline(std::cin, userInput, '\n');
int j = 0;
bool fileDirect = false;
if(!userInput.empty())
{
// Put user input into vecotr of strings
subStrs = processString(userInput);
int i = 0;
while ((i < subStrs.size()) && (subStrs[i] != ">") )
{
cmdFlgs.push_back(const_cast<char*>(subStrs[i].c_str()));
i++;
}
/*for (int i = 0; i < cmdFlgs.size(); i++)
{
std::cout << "cmdFlgs[" << i << "] = " << cmdFlgs[i] << std::endl;
std::cout << "It is: " << isspace(*cmdFlgs[i]) << std::endl;
}
*/
int j = 0;
if ( ++i < subStrs.size())
{
fileName.push_back(const_cast<char*>(subStrs[i].c_str()));
std::cout << "fileName[" << i << "] = " << fileName[i] << std::endl;
}
testFunction(cmdFlgs.size(), cmdFlgs.data(), fileName.data());
fileName.clear();
cmdFlgs.clear();
}
subStrs.clear();
subStrs.resize(1);
}
return 0;
}
答案 0 :(得分:1)
您对execvp以及shell如何工作的期望是错误的。 execvp将执行给定的程序,并将其余的命令行参数作为参数传递给程序。当您在命令行上运行它时,shell会做一些工作来理解'&gt;'符号不会传递给被调用的程序,而是被解释为重定向。
答案 1 :(得分:0)
如果未输入输出重定向运算符,则fileName
数组将为空。
if ( ++i < subStrs.size())
{
fileName.push_back(const_cast<char*>(subStrs[i].c_str()));
如果未采用此if
分支,fileName
将保持完全为空的向量。 P.S。:这const_cast
使我的眼睛流血。
testFunction(cmdFlgs.size(), cmdFlgs.data(), fileName.data());
在这种情况下,fileName.data()将是一个空指针。
您的问题是,在注释部分到位后,您的代码无效。
if (isalnum(*fname[0]) || ispunct(*fname[0]))
由于fname
参数是空指针,因此这里将有一个空指针取消引用。
此外,此代码遭遇严重的C-itis案例。这是一个主要困扰C ++代码的条件,它认为它不是C ++代码,而是C代码。
例如:
subStrs[j].push_back('\0');
这完全没必要。 std::string
会自动处理详细信息,例如始终在字符串末尾附加\ 0。这不再是C,这是C ++。并且,在C ++中,我们不会像将\0
附加到字符串那样处理愚蠢。这是std::string
的用途。
if (sameSeq)
{
subStrs[j].push_back('\0');
j++;
}
同样的事情。这些都不是必需的。此外,这里还有一个家庭作业。尝试找出sameSeq
始终为true
的原因。没有例外(免费提示,请查看前一个if
和while
条件。这里要删除更多不需要的代码。
PS。所有上述内容都是在调试器的帮助下快速确定的,即gdb
,这与您的linux机箱上的gdb
相同。这是您应该研究的另一件事:学习如何使用gdb
。