【问题标题】:Pipe implementation on C++C++ 上的管道实现
【发布时间】:2021-10-21 03:02:51
【问题描述】:

我构建了一个简单的shell来执行像% ls | cat | number这样的管道命令。当我执行正常的管道命令时,它可以工作。但是当我输入像% ls | las这样的未知命令时,我想输出像未知命令这样的错误消息: [las],但是程序的输出变得很奇怪。这是我关于管道的代码:

    void pipe_cmd(){
    int index = 0;
    char* cmds[command_num][100]; 
    char* cmd[100];

    while (index < command_num)
    {
        for(int i = 0; i < argc[index]; i++){
            cmd[i] = const_cast<char*>(command[index][i].c_str());
            cmds[index][i] = cmd[i];
        }
        cmds[index][argc[index]] = NULL;
        index++;
    }
    
    int fd[2*(command_num - 1)];
    for (int i = 0; i < command_num - 1; i++){
        if(pipe(fd + 2 * i) == -1){
            perror("Pipe failed");
            exit(1);
        }
    }

    pid_t pid;

    for (int i = 0; i < command_num; i++)
    {
        pid = fork();
        if(pid == 0){
            if (i != 0){
                dup2(fd[2 * (i - 1)], 0);
            }
            if(i != command_num - 1){
                dup2(fd[2 * i + 1], 1);
            }

            for(int j = 0; j < 2*(command_num - 1);j++){
                close(fd[j]);
            }
            if(execvp(cmds[i][0],cmds[i]) == -1){
                cerr << "Unknown command: " << "[" << cmds[i][0] << "]." << endl;
            }
        } else{
            if (i != 0){
                close(fd[2 * (i - 1)]);
                close(fd[2 * (i - 1) + 1]);
            }
            
        }
    }
    waitpid(pid, NULL, 0); 
}

我的输出看起来像:

% ls | las
Unknown command: [las].
% Unknown command: [README.md].
% Unknown command: [bin].
% % % Unknown command: [npshell.cpp].
% Unknown command: [test.html].

【问题讨论】:

    标签: c++ shell pipe


    【解决方案1】:

    在使用execvp 执行命令之前,您必须检查是否所有命令都在$PATH,如果它不存在,这意味着用户输入的命令无效。 这是一个检查命令是否存在的示例,我在这里使用了vectorsstring,因为您使用的是c++。

    #include <iostream>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <vector>
    
    std::vector<std::string> split_line(char *command) {
      std::vector<std::string> commands;
      char *token = strtok(command, " ");
      while (token != NULL) {
        commands.push_back(token);
        token = strtok(NULL, " ");
      }
      return commands;
    }
    bool does_command_exists(std::vector<std::string> path, std::string command) {
      char *c_command = const_cast<char *>(command.c_str());
    
      std::vector<std::string> args = split_line(c_command);
    
      // converting vector to char** (required for execvp)
      char **argv = (char **)malloc(sizeof(char *) * args.size());
      for (size_t i = 0; i < args.size(); i++) {
        argv[i] = const_cast<char *>(args[i].c_str());
      }
    
      struct stat stats;
      for (auto x : path) {
        x = x.append("/");
        x = x.append(argv[0]);
        if (stat(x.c_str(), &stats) == 0) {
          return true;
        }
      }
      return false;
    }
    int main(void) {
    
      std::vector<std::string> commands{"ls -l", "sort", "Something"};
    
      char *env = getenv("PATH");
      char *token = strtok(env, ":");
      std::vector<std::string> path;
    
      while (token != NULL) {
        path.push_back(token);
        token = strtok(NULL, ":");
      }
      for (auto command : commands) {
        if (!does_command_exists(path, command)) {
          std::cout << "Command: " << command << " does not exist "
                    << "\n";
          return -1;
        }
      }
      // All commands are valid, now other stuff can be done
    
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-13
      • 2014-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多