質問するログイン新規登録

質問編集履歴

6

コード修正

2018/03/20 18:11

投稿

ijuya_yika
ijuya_yika

スコア50

title CHANGED
File without changes
body CHANGED
@@ -250,7 +250,7 @@
250
250
  }
251
251
 
252
252
  if( pid2 == 0 ){
253
- if( (fd = open(cmd_right[0], O_RDWR | O_CREAT, 0600)) < 0){
253
+ if( (fd = open(cmd_right[0], O_RDWR | O_CREAT | O_APPEND, 0600)) < 0){
254
254
  perror("open failed\n");
255
255
  close(fd);
256
256
  exit(1);

5

コード修正

2018/03/20 18:11

投稿

ijuya_yika
ijuya_yika

スコア50

title CHANGED
File without changes
body CHANGED
@@ -82,7 +82,7 @@
82
82
  #endif
83
83
 
84
84
  if( (*type) != 0 ){
85
- int start = ( (*type) == 1 )? splitPosition + 2 : splitPosition + 3;
85
+ int start = ( (*type) == 1 )? splitPosition + 1 : splitPosition + 2; /* 修正:>> or | の前後にスペース無しに対応 */
86
86
  int len = strlen(command) - start;
87
87
 
88
88
  if( substr(command, part1, 0, splitPosition) < 0 ||

4

コード修正

2018/03/20 03:50

投稿

ijuya_yika
ijuya_yika

スコア50

title CHANGED
File without changes
body CHANGED
@@ -85,8 +85,11 @@
85
85
  int start = ( (*type) == 1 )? splitPosition + 2 : splitPosition + 3;
86
86
  int len = strlen(command) - start;
87
87
 
88
- substr(command, part1, 0, splitPosition);
88
+ if( substr(command, part1, 0, splitPosition) < 0 ||
89
- substr(command, part2, start, len);
89
+ substr(command, part2, start, len) < 0){
90
+ perror("substr\n");
91
+ exit(1);
92
+ }
90
93
  } else {
91
94
  strcpy(part1, command);
92
95
  }

3

コード修正訂正、質問文訂正

2018/03/20 03:12

投稿

ijuya_yika
ijuya_yika

スコア50

title CHANGED
@@ -1,1 +1,1 @@
1
- 【C言語】シェルでリダイレクトを実装したいが無限ループなってしまう
1
+ 【C言語】シェルでリダイレクトを実装したいがプロセスが無限に作成されるエラーが起きる
body CHANGED
@@ -5,7 +5,7 @@
5
5
  このコードのどこが無限ループの原因となっているのか教えていただきたいです。
6
6
 
7
7
  ***
8
-
8
+ 【追記1】
9
9
  指摘を受けて:
10
10
 
11
11
  `getCommand`の他、省略していた関数やデバッグ文を記述しました。
@@ -15,6 +15,9 @@
15
15
  以下のコードをコンパイルして動かすとパイプ、リダイレクトを含まないコマンド及びパイプコマンドは問題なく動くのですが、リダイレクトの場合にプロセスが無限に作られてしまい`CTRL+C`等でプログラムを終了できない状態になってしまいます。
16
16
 
17
17
 
18
+ ***
19
+ 【追記2】
20
+ 239行目に`exit(1)`を追加した所正常に動くようになりました。なぜここに`exit(1)`がないと無限プロセス作成エラーになるのか教えていただける方がいたらお願いしたいです。
18
21
 
19
22
  ### 該当のソースコード
20
23
 
@@ -258,6 +261,9 @@
258
261
  }
259
262
 
260
263
  close(fd);
264
+
265
+ /**** 追記2 : exit(1)がないと無限プロセスになるため追加 ****/
266
+ exit(1);
261
267
  }
262
268
  else {
263
269
  close(fds[READ]);

2

コード修正/訂正

2018/03/20 02:57

投稿

ijuya_yika
ijuya_yika

スコア50

title CHANGED
File without changes
body CHANGED
@@ -4,42 +4,259 @@
4
4
  以下のコードを実行すると無限ループに陥ってしまいます。
5
5
  このコードのどこが無限ループの原因となっているのか教えていただきたいです。
6
6
 
7
+ ***
8
+
9
+ 指摘を受けて:
10
+
11
+ `getCommand`の他、省略していた関数やデバッグ文を記述しました。
12
+
13
+ リダイレクトのみ機能していない状態だったので該当のコードのみ載せたのですが誤解を招いてしまいすみません。
14
+
15
+ 以下のコードをコンパイルして動かすとパイプ、リダイレクトを含まないコマンド及びパイプコマンドは問題なく動くのですが、リダイレクトの場合にプロセスが無限に作られてしまい`CTRL+C`等でプログラムを終了できない状態になってしまいます。
16
+
17
+
18
+
7
19
  ### 該当のソースコード
8
20
 
9
- ```C
21
+ ```C
10
22
 
23
+ #include <stdio.h>
24
+ #include <stdlib.h>
25
+ #include <unistd.h>
26
+ #include <string.h>
27
+ #include <errno.h>
28
+ #include <sys/wait.h>
29
+ #include <sys/stat.h>
30
+ #include <sys/types.h>
31
+ #include <fcntl.h>
32
+ #define MAX_ARG 50
33
+ #define READ 0
34
+ #define WRITE 1
35
+
36
+ /* @戻り値 0 => 普通のコマンド, 1 => パイプコマンド, 2 => リダイレクトコマンド */
37
+ void Type(char* command, int* type, int* splitPosition){
38
+ int pos = 0;
39
+
40
+ (*type) = 0;
41
+
42
+ while(command[pos] != '\0'){
43
+
44
+ if(command[pos] == '|'){
45
+ (*type) = 1;
46
+ (*splitPosition) = pos;
47
+ }
48
+ else if(command[pos] == '>' && command[pos+1] == '>'){
49
+ (*type) = 2;
50
+ (*splitPosition) = pos;
51
+ }
52
+
53
+ pos++;
54
+ }
55
+ }
56
+
57
+ int substr(char* S1, char* S2, int P, int L){
58
+ if( P < 0 || L < 0 || L > strlen(S1) ){
59
+ return -1;
60
+ }
61
+
62
+ for( S1 += P; *S1 != '\0' && L > 0; L--){
63
+ *S2++ = *S1++;
64
+ }
65
+
66
+ *S2 = '\0';
67
+
68
+ return 0;
69
+ }
70
+
71
+
72
+ void split(char* command, char* part1, char* part2, int* type){
73
+ int splitPosition = 0;
74
+
75
+ Type(command, type, &splitPosition);
76
+
77
+ #ifndef DEBUG
78
+ printf("splitPosition = %d\n", splitPosition);
79
+ #endif
80
+
81
+ if( (*type) != 0 ){
82
+ int start = ( (*type) == 1 )? splitPosition + 2 : splitPosition + 3;
83
+ int len = strlen(command) - start;
84
+
85
+ substr(command, part1, 0, splitPosition);
86
+ substr(command, part2, start, len);
87
+ } else {
88
+ strcpy(part1, command);
89
+ }
90
+
91
+ #ifndef DEBUG
92
+ printf("part1 = %s\n", part1);
93
+ printf("part2 = %s\n", part2);
94
+ #endif
95
+ }
96
+
97
+ void getCommand(char* command){
98
+
99
+ scanf("%255[^\n]%*[^\n]", command);
100
+ scanf("%*c");
101
+
102
+ #ifndef DEBUG
103
+ printf("command = %s\n", command);
104
+ #endif
105
+ }
106
+
107
+
108
+ int to_token(char* command, char** tokens){
109
+ int argc = 0;
110
+
111
+ tokens[argc] = strtok(command, " ");
112
+
113
+ while(argc < MAX_ARG){
114
+ tokens[++argc] = strtok(NULL, " ");
115
+
116
+ if(tokens[argc] == NULL){
117
+ break;
118
+ }
119
+ }
120
+
121
+ return argc;
122
+ }
123
+
124
+
125
+ int Parse(char* command, char** parsedCommand){
126
+ int argc = to_token(command, parsedCommand);
127
+ int ret;
128
+
129
+ if(strcmp( parsedCommand[argc - 1], "&") == 0){
130
+ parsedCommand[argc - 1] = NULL;
131
+ ret = 1;
132
+ } else {
133
+ ret = 0;
134
+ }
135
+
136
+ return ret;
137
+ }
138
+
139
+
140
+ void RegCmd(char* part1){
141
+ char* parsedCommand[20];
142
+ int background;
143
+ pid_t pid;
144
+
145
+ background = Parse(part1, parsedCommand);
146
+
147
+ if( (pid = fork()) == 0){
148
+ execvp(parsedCommand[0], parsedCommand);
149
+ perror("execvp failed\n");
150
+ exit(1);
151
+ } else {
152
+ if(!background){
153
+ waitpid(pid, NULL, 0);
154
+ }
155
+ }
156
+ }
157
+
11
- void Redirect(char* part1, char* part2){
158
+ void PipeCmd(char* part1, char* part2){
12
- char* Left[20];
159
+ char* cmd_left[20];
13
- char* Right[20];
160
+ char* cmd_right[20];
14
161
  int fds[2];
162
+ pid_t pid1, pid2;
163
+ int background;
164
+
165
+ if( pipe(fds) < 0){
166
+ perror("pipe failed\n");
167
+ exit(1);
168
+ }
169
+
170
+
171
+ background = Parse(part1, cmd_left) ||
172
+ Parse(part2, cmd_right);
173
+
174
+ if( (pid1 = fork()) < 0){
175
+ perror("fork failed\n");
176
+ exit(1);
177
+ }
178
+
179
+ if( pid1 == 0 ){
180
+ dup2(fds[READ], 0);
181
+ close(fds[WRITE]);
182
+ execvp(cmd_right[0], cmd_right);
183
+ perror("execvp failed\n");
184
+ }
185
+
186
+ if( (pid2 = fork()) < 0){
187
+ perror("fork failed\n");
188
+ exit(1);
189
+ }
190
+
191
+ if( pid2 == 0 ){
192
+ dup2(fds[WRITE], 1);
193
+ close(fds[READ]);
194
+ execvp(cmd_left[0], cmd_left);
195
+ perror("execvp failed\n");
196
+ }
197
+ else {
198
+ close(fds[0]);
199
+ close(fds[1]);
200
+
201
+ if(!background){
202
+ waitpid(pid1, NULL, 0);
203
+ waitpid(pid2, NULL, 0);
204
+ }
205
+ }
206
+ }
207
+
208
+ void RedirectCmd(char* part1, char* part2){
209
+ char* cmd_left[20];
210
+ char* cmd_right[20];
211
+ int fds[2];
15
212
  int fd;
16
213
  int count;
17
214
  pid_t pid1, pid2;
18
215
  int background;
19
216
  char c;
20
217
 
21
- pipe(fds);
218
+ if( pipe(fds) < 0){
219
+ perror("pipe failed\n");
220
+ exit(1);
221
+ }
222
+
223
+
224
+ background = Parse(part1, cmd_left) ||
225
+ Parse(part2, cmd_right);
226
+
22
227
 
23
- pid1 = fork());
228
+ if( (pid1 = fork()) < 0){
229
+ perror("fork failed\n");
230
+ exit(1);
231
+ }
24
232
 
25
- if(pid1 == 0){
233
+ if( pid1 == 0 ){
26
- // >> より左側のコマンドを実行
27
234
  dup2(fds[WRITE], 1);
28
235
  close(fds[READ]);
29
- execvp(Left[0], Left);
236
+ execvp(cmd_left[0], cmd_left);
237
+ perror("execvp failed\n");
30
238
  exit(1);
31
239
  }
32
-
33
- pid2 = fork();
34
240
 
241
+ if( (pid2 = fork()) < 0){
242
+ perror("fork failed\n");
243
+ exit(1);
244
+ }
245
+
35
- if(pid2 == 0){
246
+ if( pid2 == 0 ){
36
- // >> より右側のファイルを作成し左側のコマンドを書き込む
37
- fd = open(Right[0], O_RDWR | O_CREAT, 0600)) < 0);
247
+ if( (fd = open(cmd_right[0], O_RDWR | O_CREAT, 0600)) < 0){
248
+ perror("open failed\n");
249
+ close(fd);
250
+ exit(1);
251
+ }
252
+
38
253
  dup2(fds[READ], 0);
39
254
  close(fds[WRITE]);
255
+
40
256
  while( (count = read(0, &c, 1)) > 0){
41
257
  write(fd, &c, 1);
42
258
  }
259
+
43
260
  close(fd);
44
261
  }
45
262
  else {
@@ -53,21 +270,36 @@
53
270
 
54
271
  int main(void){
55
272
  char cmd[256];
56
- char p1[128];
273
+ char part1[128];
57
- char p2[128];
274
+ char part2[128];
58
275
  int type = -1;
59
276
 
60
277
  printf("\n> ");
61
278
  getCommand(cmd);
62
279
 
63
280
  while( (strcmp(cmd, "quit")!=0) &&
64
- (strcmp(cmd, "exit")!=0) )
281
+ (strcmp(cmd, "exit")!=0) ){
65
- // commandline は常に **** >> **** か quit or exit の形式であると想定
66
- Redirect(p1, p2);
282
+ split(cmd, part1, part2, &type);
67
283
 
284
+ if(type == 0){
285
+ RegCmd(part1);
286
+ }
287
+ else if(type == 1){
288
+ PipeCmd(part1, part2);
289
+ }
290
+ else if(type == 2){
291
+ RedirectCmd(part1, part2);
292
+ }
293
+
294
+ #ifndef DEBUG
295
+ printf("\nType = %d", type);
296
+ #endif
297
+
68
- printf("\nMyshell> ");
298
+ printf("\n> ");
69
299
  getCommand(cmd);
70
300
  }
71
301
  return 0;
72
302
  }
303
+
304
+
73
305
  ```

1

文章訂正

2018/03/20 02:49

投稿

ijuya_yika
ijuya_yika

スコア50

title CHANGED
File without changes
body CHANGED
@@ -1,7 +1,7 @@
1
1
  ### 前提・実現したいこと
2
2
 
3
3
  自作シェルでリダイレクト(>>)を実装したいのですが
4
- 以下のコード実行すると無限ループに陥ってしまいます。
4
+ 以下のコード実行すると無限ループに陥ってしまいます。
5
5
  このコードのどこが無限ループの原因となっているのか教えていただきたいです。
6
6
 
7
7
  ### 該当のソースコード