为什么尝试的文件重定向会破坏此代码
Why does attempted file redirection break this code?
这基本上应该执行用户输入的 Linux shell 命令并调用 execvp对于我的测试函数,为什么在输入命令时会像" ls -l>样本.txt命令不仅不执行,而且文件也不会创建。
但是,如果我在没有重定向的情况下运行该命令,它可以正常工作。
此外,在附加文件名的失败运行后,shell 会完全损坏,即使是以前有效的正常命令也无法正常工作。
似乎 ls -l 有时会破坏下一个输入命令。然后它变得无法找到ls或任何其他命令。
编辑:在任何失败的命令之后,它将无法 fin 任何以前工作的命令。
#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(' ');
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;
}
你对 execvp 和 shell 如何工作的期望是错误的。 execvp 将执行给定的程序,并将其余的命令行参数作为参数传递给程序。 当你在命令行上运行它时,shell 会做一些工作来理解">"符号不会传递给被调用的程序,而是被解释为重定向。
如果未输入输出重定向运算符,则fileName
数组将为空。
if ( ++i < subStrs.size())
{
fileName.push_back(const_cast<char*>(subStrs[i].c_str()));
如果不采用此if
分支,fileName
将保持为完全空的向量。PS:这个const_cast
让我的眼睛流血。
testFunction(cmdFlgs.size(), cmdFlgs.data(), fileName.data());
在这种情况下,fileName.data() 将是一个空指针。
您的问题是,在注释部分到位的情况下,您的代码不起作用。
if (isalnum(*fname[0]) || ispunct(*fname[0]))
由于 fname
参数是空指针,因此此处将取消引用空指针。
此外,此代码正在遭受严重的C-it情况。这种情况主要困扰C++认为它不是C++代码而是 C 代码的代码。
例如:
subStrs[j].push_back(' ');
这是完全没有必要的。 std::string
会自动处理详细信息,例如始终在字符串末尾附加 \0。这不再是C,这是C++。而且,在C++中,我们不会处理像将