質問編集履歴

6

コード修正

2018/03/20 18:11

投稿

ijuya_yika
ijuya_yika

スコア50

test CHANGED
File without changes
test CHANGED
@@ -502,7 +502,7 @@
502
502
 
503
503
  if( pid2 == 0 ){
504
504
 
505
- if( (fd = open(cmd_right[0], O_RDWR | O_CREAT, 0600)) < 0){
505
+ if( (fd = open(cmd_right[0], O_RDWR | O_CREAT | O_APPEND, 0600)) < 0){
506
506
 
507
507
  perror("open failed\n");
508
508
 

5

コード修正

2018/03/20 18:11

投稿

ijuya_yika
ijuya_yika

スコア50

test CHANGED
File without changes
test CHANGED
@@ -166,7 +166,7 @@
166
166
 
167
167
  if( (*type) != 0 ){
168
168
 
169
- int start = ( (*type) == 1 )? splitPosition + 2 : splitPosition + 3;
169
+ int start = ( (*type) == 1 )? splitPosition + 1 : splitPosition + 2; /* 修正:>> or | の前後にスペース無しに対応 */
170
170
 
171
171
  int len = strlen(command) - start;
172
172
 

4

コード修正

2018/03/20 03:50

投稿

ijuya_yika
ijuya_yika

スコア50

test CHANGED
File without changes
test CHANGED
@@ -172,9 +172,15 @@
172
172
 
173
173
 
174
174
 
175
- substr(command, part1, 0, splitPosition);
175
+ if( substr(command, part1, 0, splitPosition) < 0 ||
176
-
176
+
177
- substr(command, part2, start, len);
177
+ substr(command, part2, start, len) < 0){
178
+
179
+ perror("substr\n");
180
+
181
+ exit(1);
182
+
183
+ }
178
184
 
179
185
  } else {
180
186
 

3

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

2018/03/20 03:12

投稿

ijuya_yika
ijuya_yika

スコア50

test CHANGED
@@ -1 +1 @@
1
- 【C言語】シェルでリダイレクトを実装したいが無限プになってしまう
1
+ 【C言語】シェルでリダイレクトを実装したいがプロセスが無限に作成されるエラが起きる
test CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  ***
14
14
 
15
-
15
+ 【追記1】
16
16
 
17
17
  指摘を受けて:
18
18
 
@@ -32,6 +32,12 @@
32
32
 
33
33
 
34
34
 
35
+ ***
36
+
37
+ 【追記2】
38
+
39
+ 239行目に`exit(1)`を追加した所正常に動くようになりました。なぜここに`exit(1)`がないと無限プロセス作成エラーになるのか教えていただける方がいたらお願いしたいです。
40
+
35
41
 
36
42
 
37
43
  ### 該当のソースコード
@@ -518,6 +524,12 @@
518
524
 
519
525
  close(fd);
520
526
 
527
+
528
+
529
+ /**** 追記2 : exit(1)がないと無限プロセスになるため追加 ****/
530
+
531
+ exit(1);
532
+
521
533
  }
522
534
 
523
535
  else {

2

コード修正/訂正

2018/03/20 02:57

投稿

ijuya_yika
ijuya_yika

スコア50

test CHANGED
File without changes
test CHANGED
@@ -10,22 +10,416 @@
10
10
 
11
11
 
12
12
 
13
+ ***
14
+
15
+
16
+
17
+ 指摘を受けて:
18
+
19
+
20
+
21
+ `getCommand`の他、省略していた関数やデバッグ文を記述しました。
22
+
23
+
24
+
25
+ リダイレクトのみ機能していない状態だったので該当のコードのみ載せたのですが誤解を招いてしまいすみません。
26
+
27
+
28
+
29
+ 以下のコードをコンパイルして動かすとパイプ、リダイレクトを含まないコマンド及びパイプコマンドは問題なく動くのですが、リダイレクトの場合にプロセスが無限に作られてしまい`CTRL+C`等でプログラムを終了できない状態になってしまいます。
30
+
31
+
32
+
33
+
34
+
35
+
36
+
13
37
  ### 該当のソースコード
14
38
 
15
39
 
16
40
 
17
- ```C
18
-
19
-
20
-
21
- void Redirect(char* part1, char* part2){
22
-
23
- char* Left[20];
24
-
25
- char* Right[20];
41
+ ```C
42
+
43
+
44
+
45
+ #include <stdio.h>
46
+
47
+ #include <stdlib.h>
48
+
49
+ #include <unistd.h>
50
+
51
+ #include <string.h>
52
+
53
+ #include <errno.h>
54
+
55
+ #include <sys/wait.h>
56
+
57
+ #include <sys/stat.h>
58
+
59
+ #include <sys/types.h>
60
+
61
+ #include <fcntl.h>
62
+
63
+ #define MAX_ARG 50
64
+
65
+ #define READ 0
66
+
67
+ #define WRITE 1
68
+
69
+
70
+
71
+ /* @戻り値 0 => 普通のコマンド, 1 => パイプコマンド, 2 => リダイレクトコマンド */
72
+
73
+ void Type(char* command, int* type, int* splitPosition){
74
+
75
+ int pos = 0;
76
+
77
+
78
+
79
+ (*type) = 0;
80
+
81
+
82
+
83
+ while(command[pos] != '\0'){
84
+
85
+
86
+
87
+ if(command[pos] == '|'){
88
+
89
+ (*type) = 1;
90
+
91
+ (*splitPosition) = pos;
92
+
93
+ }
94
+
95
+ else if(command[pos] == '>' && command[pos+1] == '>'){
96
+
97
+ (*type) = 2;
98
+
99
+ (*splitPosition) = pos;
100
+
101
+ }
102
+
103
+
104
+
105
+ pos++;
106
+
107
+ }
108
+
109
+ }
110
+
111
+
112
+
113
+ int substr(char* S1, char* S2, int P, int L){
114
+
115
+ if( P < 0 || L < 0 || L > strlen(S1) ){
116
+
117
+ return -1;
118
+
119
+ }
120
+
121
+
122
+
123
+ for( S1 += P; *S1 != '\0' && L > 0; L--){
124
+
125
+ *S2++ = *S1++;
126
+
127
+ }
128
+
129
+
130
+
131
+ *S2 = '\0';
132
+
133
+
134
+
135
+ return 0;
136
+
137
+ }
138
+
139
+
140
+
141
+
142
+
143
+ void split(char* command, char* part1, char* part2, int* type){
144
+
145
+ int splitPosition = 0;
146
+
147
+
148
+
149
+ Type(command, type, &splitPosition);
150
+
151
+
152
+
153
+ #ifndef DEBUG
154
+
155
+ printf("splitPosition = %d\n", splitPosition);
156
+
157
+ #endif
158
+
159
+
160
+
161
+ if( (*type) != 0 ){
162
+
163
+ int start = ( (*type) == 1 )? splitPosition + 2 : splitPosition + 3;
164
+
165
+ int len = strlen(command) - start;
166
+
167
+
168
+
169
+ substr(command, part1, 0, splitPosition);
170
+
171
+ substr(command, part2, start, len);
172
+
173
+ } else {
174
+
175
+ strcpy(part1, command);
176
+
177
+ }
178
+
179
+
180
+
181
+ #ifndef DEBUG
182
+
183
+ printf("part1 = %s\n", part1);
184
+
185
+ printf("part2 = %s\n", part2);
186
+
187
+ #endif
188
+
189
+ }
190
+
191
+
192
+
193
+ void getCommand(char* command){
194
+
195
+
196
+
197
+ scanf("%255[^\n]%*[^\n]", command);
198
+
199
+ scanf("%*c");
200
+
201
+
202
+
203
+ #ifndef DEBUG
204
+
205
+ printf("command = %s\n", command);
206
+
207
+ #endif
208
+
209
+ }
210
+
211
+
212
+
213
+
214
+
215
+ int to_token(char* command, char** tokens){
216
+
217
+ int argc = 0;
218
+
219
+
220
+
221
+ tokens[argc] = strtok(command, " ");
222
+
223
+
224
+
225
+ while(argc < MAX_ARG){
226
+
227
+ tokens[++argc] = strtok(NULL, " ");
228
+
229
+
230
+
231
+ if(tokens[argc] == NULL){
232
+
233
+ break;
234
+
235
+ }
236
+
237
+ }
238
+
239
+
240
+
241
+ return argc;
242
+
243
+ }
244
+
245
+
246
+
247
+
248
+
249
+ int Parse(char* command, char** parsedCommand){
250
+
251
+ int argc = to_token(command, parsedCommand);
252
+
253
+ int ret;
254
+
255
+
256
+
257
+ if(strcmp( parsedCommand[argc - 1], "&") == 0){
258
+
259
+ parsedCommand[argc - 1] = NULL;
260
+
261
+ ret = 1;
262
+
263
+ } else {
264
+
265
+ ret = 0;
266
+
267
+ }
268
+
269
+
270
+
271
+ return ret;
272
+
273
+ }
274
+
275
+
276
+
277
+
278
+
279
+ void RegCmd(char* part1){
280
+
281
+ char* parsedCommand[20];
282
+
283
+ int background;
284
+
285
+ pid_t pid;
286
+
287
+
288
+
289
+ background = Parse(part1, parsedCommand);
290
+
291
+
292
+
293
+ if( (pid = fork()) == 0){
294
+
295
+ execvp(parsedCommand[0], parsedCommand);
296
+
297
+ perror("execvp failed\n");
298
+
299
+ exit(1);
300
+
301
+ } else {
302
+
303
+ if(!background){
304
+
305
+ waitpid(pid, NULL, 0);
306
+
307
+ }
308
+
309
+ }
310
+
311
+ }
312
+
313
+
314
+
315
+ void PipeCmd(char* part1, char* part2){
316
+
317
+ char* cmd_left[20];
318
+
319
+ char* cmd_right[20];
26
320
 
27
321
  int fds[2];
28
322
 
323
+ pid_t pid1, pid2;
324
+
325
+ int background;
326
+
327
+
328
+
329
+ if( pipe(fds) < 0){
330
+
331
+ perror("pipe failed\n");
332
+
333
+ exit(1);
334
+
335
+ }
336
+
337
+
338
+
339
+
340
+
341
+ background = Parse(part1, cmd_left) ||
342
+
343
+ Parse(part2, cmd_right);
344
+
345
+
346
+
347
+ if( (pid1 = fork()) < 0){
348
+
349
+ perror("fork failed\n");
350
+
351
+ exit(1);
352
+
353
+ }
354
+
355
+
356
+
357
+ if( pid1 == 0 ){
358
+
359
+ dup2(fds[READ], 0);
360
+
361
+ close(fds[WRITE]);
362
+
363
+ execvp(cmd_right[0], cmd_right);
364
+
365
+ perror("execvp failed\n");
366
+
367
+ }
368
+
369
+
370
+
371
+ if( (pid2 = fork()) < 0){
372
+
373
+ perror("fork failed\n");
374
+
375
+ exit(1);
376
+
377
+ }
378
+
379
+
380
+
381
+ if( pid2 == 0 ){
382
+
383
+ dup2(fds[WRITE], 1);
384
+
385
+ close(fds[READ]);
386
+
387
+ execvp(cmd_left[0], cmd_left);
388
+
389
+ perror("execvp failed\n");
390
+
391
+ }
392
+
393
+ else {
394
+
395
+ close(fds[0]);
396
+
397
+ close(fds[1]);
398
+
399
+
400
+
401
+ if(!background){
402
+
403
+ waitpid(pid1, NULL, 0);
404
+
405
+ waitpid(pid2, NULL, 0);
406
+
407
+ }
408
+
409
+ }
410
+
411
+ }
412
+
413
+
414
+
415
+ void RedirectCmd(char* part1, char* part2){
416
+
417
+ char* cmd_left[20];
418
+
419
+ char* cmd_right[20];
420
+
421
+ int fds[2];
422
+
29
423
  int fd;
30
424
 
31
425
  int count;
@@ -38,50 +432,90 @@
38
432
 
39
433
 
40
434
 
41
- pipe(fds);
435
+ if( pipe(fds) < 0){
436
+
437
+ perror("pipe failed\n");
438
+
439
+ exit(1);
440
+
441
+ }
442
+
443
+
444
+
445
+
446
+
447
+ background = Parse(part1, cmd_left) ||
448
+
449
+ Parse(part2, cmd_right);
450
+
451
+
42
452
 
43
453
 
44
454
 
45
- pid1 = fork());
455
+ if( (pid1 = fork()) < 0){
456
+
46
-
457
+ perror("fork failed\n");
458
+
47
-
459
+ exit(1);
460
+
48
-
461
+ }
462
+
463
+
464
+
49
- if(pid1 == 0){
465
+ if( pid1 == 0 ){
50
-
51
- // >> より左側のコマンドを実行
52
466
 
53
467
  dup2(fds[WRITE], 1);
54
468
 
55
469
  close(fds[READ]);
56
470
 
57
- execvp(Left[0], Left);
471
+ execvp(cmd_left[0], cmd_left);
472
+
58
-
473
+ perror("execvp failed\n");
474
+
59
- exit(1);
475
+ exit(1);
60
-
476
+
61
- }
477
+ }
62
-
63
-
64
-
478
+
479
+
480
+
65
- pid2 = fork();
481
+ if( (pid2 = fork()) < 0){
482
+
66
-
483
+ perror("fork failed\n");
484
+
67
-
485
+ exit(1);
486
+
68
-
487
+ }
488
+
489
+
490
+
69
- if(pid2 == 0){
491
+ if( pid2 == 0 ){
70
-
71
- // >> より右側のファイルを作成し左側のコマンドを書き込む
492
+
72
-
73
- fd = open(Right[0], O_RDWR | O_CREAT, 0600)) < 0);
493
+ if( (fd = open(cmd_right[0], O_RDWR | O_CREAT, 0600)) < 0){
494
+
495
+ perror("open failed\n");
496
+
497
+ close(fd);
498
+
499
+ exit(1);
500
+
501
+ }
502
+
503
+
74
504
 
75
505
  dup2(fds[READ], 0);
76
506
 
77
507
  close(fds[WRITE]);
78
508
 
509
+
510
+
79
511
  while( (count = read(0, &c, 1)) > 0){
80
512
 
81
513
  write(fd, &c, 1);
82
514
 
83
515
  }
84
516
 
517
+
518
+
85
519
  close(fd);
86
520
 
87
521
  }
@@ -108,9 +542,9 @@
108
542
 
109
543
  char cmd[256];
110
544
 
111
- char p1[128];
545
+ char part1[128];
112
-
546
+
113
- char p2[128];
547
+ char part2[128];
114
548
 
115
549
  int type = -1;
116
550
 
@@ -124,15 +558,41 @@
124
558
 
125
559
  while( (strcmp(cmd, "quit")!=0) &&
126
560
 
127
- (strcmp(cmd, "exit")!=0) )
561
+ (strcmp(cmd, "exit")!=0) ){
128
-
562
+
129
- // commandline は常に **** >> **** か quit or exit の形式であると想定
563
+ split(cmd, part1, part2, &type);
564
+
565
+
566
+
130
-
567
+ if(type == 0){
568
+
569
+ RegCmd(part1);
570
+
571
+ }
572
+
573
+ else if(type == 1){
574
+
575
+ PipeCmd(part1, part2);
576
+
577
+ }
578
+
579
+ else if(type == 2){
580
+
131
- Redirect(p1, p2);
581
+ RedirectCmd(part1, part2);
582
+
132
-
583
+ }
584
+
585
+
586
+
133
-
587
+ #ifndef DEBUG
588
+
134
-
589
+ printf("\nType = %d", type);
590
+
591
+ #endif
592
+
593
+
594
+
135
- printf("\nMyshell> ");
595
+ printf("\n> ");
136
596
 
137
597
  getCommand(cmd);
138
598
 
@@ -142,4 +602,8 @@
142
602
 
143
603
  }
144
604
 
605
+
606
+
607
+
608
+
145
609
  ```

1

文章訂正

2018/03/20 02:49

投稿

ijuya_yika
ijuya_yika

スコア50

test CHANGED
File without changes
test CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  自作シェルでリダイレクト(>>)を実装したいのですが
6
6
 
7
- 以下のコード実行すると無限ループに陥ってしまいます。
7
+ 以下のコード実行すると無限ループに陥ってしまいます。
8
8
 
9
9
  このコードのどこが無限ループの原因となっているのか教えていただきたいです。
10
10