1// pipe.c
2// ํ์ดํ ๊ตฌํ
3// ์ฌ๋ฌ ๋ช
๋ น์ด๋ฅผ | ๋ก ์ฐ๊ฒฐํ์ฌ ์คํ
4// ์ปดํ์ผ: gcc -c pipe.c ๋๋ ๋ค๋ฅธ ํ์ผ๊ณผ ํจ๊ป ๋งํฌ
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <unistd.h>
10#include <sys/wait.h>
11
12#define MAX_PIPES 10
13
14// ํ์ดํ๋ก ๋ถ๋ฆฌ๋ ๋ช
๋ น์ด ์ ์นด์ดํธ
15int count_pipes(char** args) {
16 int count = 0;
17 for (int i = 0; args[i]; i++) {
18 if (strcmp(args[i], "|") == 0) count++;
19 }
20 return count;
21}
22
23// ํ์ดํ ์์น์์ args ๋ถ๋ฆฌ
24// commands[0] = ์ฒซ ๋ฒ์งธ ๋ช
๋ น์ด์ args
25// commands[1] = ๋ ๋ฒ์งธ ๋ช
๋ น์ด์ args
26// ...
27int split_by_pipe(char** args, char*** commands) {
28 int cmd_count = 0;
29 commands[cmd_count++] = args;
30
31 for (int i = 0; args[i]; i++) {
32 if (strcmp(args[i], "|") == 0) {
33 args[i] = NULL; // ํ์ดํ ์์น๋ฅผ NULL๋ก
34 if (args[i + 1]) {
35 commands[cmd_count++] = &args[i + 1];
36 }
37 }
38 }
39
40 return cmd_count;
41}
42
43// ํ์ดํ ์คํ
44void execute_pipe(char** args) {
45 char** commands[MAX_PIPES + 1];
46 int cmd_count = split_by_pipe(args, commands);
47
48 if (cmd_count == 1) {
49 // ํ์ดํ ์์: ์ผ๋ฐ ์คํ
50 pid_t pid = fork();
51 if (pid == 0) {
52 execvp(commands[0][0], commands[0]);
53 perror(commands[0][0]);
54 exit(EXIT_FAILURE);
55 } else if (pid > 0) {
56 wait(NULL);
57 } else {
58 perror("fork");
59 }
60 return;
61 }
62
63 int pipes[MAX_PIPES][2]; // ํ์ดํ ํ์ผ ๋์คํฌ๋ฆฝํฐ
64
65 // ํ์ดํ ์์ฑ
66 for (int i = 0; i < cmd_count - 1; i++) {
67 if (pipe(pipes[i]) < 0) {
68 perror("pipe");
69 return;
70 }
71 }
72
73 // ๊ฐ ๋ช
๋ น์ด ์คํ
74 for (int i = 0; i < cmd_count; i++) {
75 pid_t pid = fork();
76
77 if (pid == 0) {
78 // ์์ ํ๋ก์ธ์ค
79
80 // ์ด์ ํ์ดํ์ ์ฝ๊ธฐ ๋์ stdin์ผ๋ก
81 if (i > 0) {
82 dup2(pipes[i - 1][0], STDIN_FILENO);
83 }
84
85 // ๋ค์ ํ์ดํ์ ์ฐ๊ธฐ ๋์ stdout์ผ๋ก
86 if (i < cmd_count - 1) {
87 dup2(pipes[i][1], STDOUT_FILENO);
88 }
89
90 // ๋ชจ๋ ํ์ดํ ๋ซ๊ธฐ
91 for (int j = 0; j < cmd_count - 1; j++) {
92 close(pipes[j][0]);
93 close(pipes[j][1]);
94 }
95
96 // ๋ช
๋ น์ด ์คํ
97 execvp(commands[i][0], commands[i]);
98 perror(commands[i][0]);
99 exit(EXIT_FAILURE);
100
101 } else if (pid < 0) {
102 perror("fork");
103 return;
104 }
105 }
106
107 // ๋ถ๋ชจ: ๋ชจ๋ ํ์ดํ ๋ซ๊ธฐ
108 for (int i = 0; i < cmd_count - 1; i++) {
109 close(pipes[i][0]);
110 close(pipes[i][1]);
111 }
112
113 // ๋ชจ๋ ์์ ํ๋ก์ธ์ค ๋๊ธฐ
114 for (int i = 0; i < cmd_count; i++) {
115 wait(NULL);
116 }
117}
118
119// ํ
์คํธ์ฉ ๋ฉ์ธ ํจ์
120#ifdef TEST_PIPE
121#define MAX_INPUT 1024
122#define MAX_ARGS 64
123
124int parse_args(char* input, char** args) {
125 int argc = 0;
126 char* token = strtok(input, " \t\n");
127 while (token && argc < MAX_ARGS - 1) {
128 args[argc++] = token;
129 token = strtok(NULL, " \t\n");
130 }
131 args[argc] = NULL;
132 return argc;
133}
134
135int main(void) {
136 char input[MAX_INPUT];
137 char* args[MAX_ARGS];
138
139 printf("=== ํ์ดํ ํ
์คํธ ===\n");
140 printf("์์ ๋ช
๋ น์ด:\n");
141 printf(" ls -l | grep \".c\"\n");
142 printf(" cat /etc/passwd | wc -l\n");
143 printf(" ps aux | grep bash | head -5\n");
144 printf(" ls | sort | uniq\n");
145 printf("\n์ข
๋ฃ: exit ๋๋ Ctrl+D\n\n");
146
147 while (1) {
148 printf("pipe> ");
149 fflush(stdout);
150
151 if (fgets(input, sizeof(input), stdin) == NULL) {
152 printf("\n");
153 break;
154 }
155
156 if (input[0] == '\n') continue;
157
158 // ์
๋ ฅ ๋ณต์ฌ
159 char input_copy[MAX_INPUT];
160 strncpy(input_copy, input, sizeof(input_copy));
161
162 int argc = parse_args(input_copy, args);
163 if (argc == 0) continue;
164
165 if (strcmp(args[0], "exit") == 0) {
166 printf("์ข
๋ฃํฉ๋๋ค.\n");
167 break;
168 }
169
170 // ํ์ดํ ์คํ
171 execute_pipe(args);
172 }
173
174 return 0;
175}
176#endif