我正在编写一个代码,它将在其中执行Linux命令管道。基本上在我的代码中,它将解析用户输入命令,然后使用execvp函数运行它。
但是,要做到这一点,我需要知道命令及其参数。我一直在试图使解析正确工作,但是,当我做一个测试用例时,来自存储各自程序的两个数组的输出似乎是相同的。命令/参数存储在名为prgname1prgname2的char数组中。
例如,如果我要用参数“ps aux | grep [username]”运行我的程序,那么prgname1[0]和prgname2[0]的输出都是[username]。它们应该分别是psgrep
有人可以看看我的代码,看看我可能在哪里有一个错误,这是导致这一点?
谢谢!

#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <iostream>

#define MAX_PARA_NUM 5
#define MAX_COMMAND_LEN 1024

using namespace std;

int main(int argc, char *argv[]) {
char *prgname1[MAX_PARA_NUM], *prgname2[MAX_PARA_NUM];
char command[MAX_COMMAND_LEN];
int pfd[2];
pipe(pfd);
pid_t cid1, cid2;

char *full = argv[1];
char str[MAX_COMMAND_LEN];
int i = 0;
int j = 0;
int k = 0;
int ind = 0;
while (ind < strlen(full)) {
    if (full[ind] == ' ') {
        strncpy(command, str, i);
        cout << command << endl;
        prgname1[j] = command;
        j++;
        i = 0;
        ind++;
    }
    else {
        str[i] = full[ind];
        i++;
        ind++;
    }

    if(full[ind] == '|') {
        i = 0;
        j = 0;
        ind+=2;
        while (ind < strlen(full)) {
            if (full[ind] == ' ') {
                strncpy(command, str, i);
                cout << command << endl;
                prgname2[j] = command;
                j++;
                i = 0;
                ind++;
            }
            else {
                str[i] = full[ind];
                i++;
                ind++;
            }
            if (ind == strlen(full)) {
                strncpy(command, str, i);
                cout << command << endl;
                prgname2[j] = command;
                break;
            }
        }
    }
}

    // test output here not working correctly
cout << prgname1[0] << endl;
cout << prgname2[0] << endl;

// exits if no parameters passed
if (argc != 2) {
    cout << "Usage:" << argv[0] << endl;
    exit(EXIT_FAILURE);
}

// exits if there is a pipe error
if (pipe(pfd) == -1) {
    cerr << "pipe" << endl;
    exit(EXIT_FAILURE);
}
cid1 = fork();  // creates child process 1

// exits if there is a fork error
if (cid1 == -1 || cid2 == -1) {
    cerr << "fork";
    exit(EXIT_FAILURE);
}
// 1st child process executes and writes to the pipe
if (cid1 == 0) {
    char **p = prgname1;
    close(1);   // closes stdout
    dup(pfd[1]);    // connects pipe output to stdout
    close(pfd[0]);  // closes pipe input as it is not needed
    close(pfd[1]);  // closes pipe output as pipe is connected
    execvp(prgname1[0], p);
    cerr << "execlp 1 failed" << endl;
    cid2 = fork();
}
// 2nd child process reads from the pipe and executes
else if (cid2 == 0) {
    char **p = prgname2;
    close(0);   // closes stdin
    dup(pfd[0]);    // connects pipe input to stdin
    close(pfd[0]);  // closes pipe input as pipe is connected
    close(pfd[1]);  // closes pipe output as it is not needed
    execvp(prgname2[0], p);
    cerr << "execlp 2 failed" << endl;
}
else {
    sleep(1);
    waitpid(cid1, NULL, 0);
    waitpid(cid2, NULL, 0);
    cout << "Program successfully completed" << endl;
    exit(EXIT_SUCCESS);
}
return 0;

}

最佳答案

argv[1]为您提供命令行上的第一个参数,而不是整个命令行。如果要将命令行参数的完整列表传递到进程中,则需要在每个参数之间附加一个空格。
此外,在处理时,您将argv[1]的指针设置为argv[2],因此每次设置给定的字符指针时,它们都指向相同的位置(因此,它们都是相同的值)。您需要为argv[argc - 1]中的每个元素分配空间,并将prgname1[index]复制到其中(使用command)。或者,使用prgname1command可以消除大部分当前代码。

10-07 13:01