/* * 简单的shell管道模拟实现 */
#include <unistd.h> #include <string.h> #include <stdio.h>
#define MAX_OPT_NUM 32 // 最多选项个数
#define MAX_OPT_LEN 128 // 最大选项长度
void separatecmd(const char *cmd, char **argv1, char **argv2);
int main() { // -----------------------
// 得到两个命令
// -----------------------
char cmd[128]; char **argv1 = malloc(sizeof(char*)*MAX_OPT_NUM); char **argv2 = malloc(sizeof(char*)*MAX_OPT_NUM); memset(argv1, 0, sizeof(argv1)); memset(argv2, 0, sizeof(argv2)); printf("input two command seperated by |, stdout of cmd1 will be redirected to stdin of cmd2\n"); printf(">"); fgets(cmd, 128, stdin); cmd[strlen(cmd)-1] = 0; // 最后一个换行符要去掉, 否则execvp报错
separatecmd(cmd, argv1, argv2);
int pid; if((pid = fork()) == 0) { int fd[2]; pipe(fd); if(fork() == 0) // 孙进程 执行第二个命令
{ close(fd[1]); dup2(fd[0], 0); execvp(argv2[0], argv2); }
close(fd[0]); dup2(fd[1], 1); execvp(argv1[0], argv1); // 子进程 执行第一个命令
} wait(NULL);
return 0; }
void separatecmd(const char *cmd, char **argv1, char **argv2) { int cmd_opt_cnt1 = 0; int cmd_opt_cnt2 = 0; char token[MAX_OPT_LEN]; memset(token, 0, sizeof(token)); int token_cnt = 0; int flag = 0; // 现在是命令1还是命令2
for(int i=0; i<strlen(cmd); i++) { if(cmd[i] == '|' || cmd[i] == ' ') { if(strlen(token) > 0) { if(flag == 0) // command 1
{ argv1[cmd_opt_cnt1] = malloc(strlen(token) + 1); strcpy(argv1[cmd_opt_cnt1], token); cmd_opt_cnt1 ++; } else // command 2
{ argv2[cmd_opt_cnt2] = malloc(strlen(token) + 1); strcpy(argv2[cmd_opt_cnt2], token); cmd_opt_cnt2 ++; } } if(cmd[i] == '|') { flag = 1; } memset(token, 0, sizeof(token)); token_cnt = 0; } else { token[token_cnt] = cmd[i]; token_cnt ++; } } if(token_cnt > 0) { argv2[cmd_opt_cnt2] = malloc(strlen(token) + 1); strcpy(argv2[cmd_opt_cnt2], token); cmd_opt_cnt2 ++; } }
|