-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpipeController.c
More file actions
133 lines (90 loc) · 3.84 KB
/
pipeController.c
File metadata and controls
133 lines (90 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "eggshell.h"
//pipes pipeLine containing more than one command
void pipePipeLine(char * cmdArray[MAX_COMMANDS][MAX_ARGS], int cmdAmnt){
int pAmnt = cmdAmnt - 1; //amount of pipes
int fdAmnt = 2*pAmnt; //every pipe has two file descriptors
int fd[pAmnt * 2]; //initializes needed file descriptors
int status; //used for waiting in the parent
int c = 0; //initialized new counter for commands
int j = 0; //counter for the first fd in each pipe
pid_t pid; //process id of the current process
//Creates all needed pipes at the start
for(int i = 0; i < pAmnt; i++){
if(pipe(fd + i*2) < 0){
perror("Error: Pipe creation has failed");
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return;
}
}
//traverses through commands, setting up their read and/or write in piping
for(c; cmdArray[c][0] != NULL; c++){
//forks the current process
if( (pid = fork() ) < 0){
perror("Error: forking process whilst traversing the pipeLine has failed");
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return;
}
//accesses child
if(pid == 0){
//child writes to the next command if not the last command
if(c!=cmdAmnt-1){
//sets the current command to write to the next
if(dup2(fd[j+1], STDOUT_FILENO) < 0){
perror("Error: writing process whilst traversing the pipeLine has failed");
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
exit(EXIT_FAILURE);
}
}
//child reads from the previous command if not the first command
if(c!=0){
//sets the current command to read from the previous
if(dup2(fd[j-2], STDIN_FILENO) < 0){
perror("Error: reading process whilst traversing the pipeLine has failed");
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
exit(EXIT_FAILURE);
}
}
//closes the current ends of the current pipe
for(int i = 0; i < fdAmnt; i++){
close(fd[i]);
}
checkInputOutput(cmdArray[c]);
exit(0);
}
j+=2;
}
//parent closes all the pipes in the pipeLine
for(int i = 0; i < fdAmnt; i++){
close(fd[i]);
}
//parent waits for children
for(int i = 0; i <= pAmnt; i++){
wait(&status);
}
}
//checks for any piping symbols in the input command and constructs array of tokenized commands that pipe to each other
void checkPipeLine(char * args[MAX_ARGS]){
char * cmdArray[MAX_COMMANDS][MAX_ARGS] = {{NULL}}; //stores all commands from the pipeline (stores just 1 when no piping occurs)
int i; //initialized counter for for loop
int j = 0; //initialized counter for copying contents from args[i] to cmdArray
int c = 0; //initialized counter for cmdArray
//traverses through arguments looking for redirection symbols
for(i = 0; args[i] != NULL; i++){
//match found with |
if(strcmp(args[i], "|") == 0){
cmdArray[c][j] = NULL; //sets end to command before pipe
j = 0; //re-initializes argument counter for next command
c++; //increments command counter
}
else{
cmdArray[c][j] = args[i];
j++;
}
}
cmdArray[c][j] = NULL; //sets end to last command without pipe | after it
c++; //increments command counter
//if piping occurs pass to pipePipeLine phase
if(c > 1) pipePipeLine(cmdArray, c);
//if no piping occurs just pass first and only command to parseInputOutput phase
else checkInputOutput(cmdArray[0]);
}