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