-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathioController.c
More file actions
278 lines (171 loc) · 6.96 KB
/
ioController.c
File metadata and controls
278 lines (171 loc) · 6.96 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#include "eggshell.h"
//stdin set to point to fileName
int stdinToFile(char * fileName){
fflush(stdin); //used as a safety precaution
int fd1; //initialized file descriptor 1
//sets file descriptor for file for reading file
fd1 = open(fileName, O_RDONLY);
if(fd1 < 0){
printf("Error: Failed to open the file \"%s\" for reading\n", fileName);
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return -1;
}
int fd2 = dup(STDIN_FILENO); //sets input to file descriptor instead of stdin
if(fd2 < 0){
printf("Error: Failed to duplicate standard input\n");
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return -1;
}
//restores fd1
if(dup2(fd1, STDIN_FILENO) < 0){
printf("Error: Failed to duplicate the file \"%s\" for standard input\n", fileName);
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return -1;
}
close(fd1);
return fd2;
}
//resets stdin back to normal using pointer made in stdinToFile()
void stdinToNormal(int fd2){
fflush(stdin); //safety precaution
//restores fd2
if(dup2(fd2, STDIN_FILENO) < 0){
printf("Error: Failed to reinstate standard input\n");
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return;
}
close(fd2);
}
//redirects stdin to string by tempFile "hereString.tmp," catering for symbol '<<<'
void redirectInputString(char * cmd[MAX_ARGS], char * stringArray[MAX_ARGS]){
/* Creates temporary file and stores string */
char * fileName = "hereString.tmp";
FILE *f = fopen("hereString.tmp", "w+");
for(int i = 0; stringArray[i] != NULL; i++){
if(stringArray[i+1] == NULL)fprintf(f, "%s", stringArray[i]);
else fprintf(f, "%s ", stringArray[i]);
}
fclose(f);
/* Connect standard input to given file*/
int fd2 = stdinToFile(fileName); //returns fd2 for later use for reversion
//if -1 is returned, error occurred and printed so just return
if(fd2 == -1){
return;
}
/* Write to standard input */
checkCmd(cmd); //parses command
/* Reconnect original standard input */
stdinToNormal(fd2);
remove(fileName); //removes temporary file
}
//redirects stdin to newly created file "fileName," catering for symbol '<'
void redirectInputFile(char * cmd[MAX_ARGS], char * fileName){
/* Connect standard output to given file*/
int fd2 = stdinToFile(fileName); //returns fd2 for later use for reversion
//if -1 is returned, error occurred and printed so just return
if(fd2 == -1){
return;
}
/* Write to standard input */
checkCmd(cmd); //parses command
/* Reconnect original standard input */
stdinToNormal(fd2);
}
//sets stdout to point to fileName
int stdoutToFile(char * fileName, int flag){
fflush(stdout); //used as a safety precaution
int fd1; //initialized file descriptor 1
//sets file descriptor for file for creating file
if(flag == 1) fd1 = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
//sets file descriptor for appending to file when flag is 2
else fd1 = open(fileName, O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if(fd1 < 0){
printf("Error: Failed to open the file \"%s\" for writing\n", fileName);
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return -1;
}
int fd2 = dup(STDOUT_FILENO); //sets output to file descriptor instead of stdout
if(fd2 < 0){
printf("Error: Failed to duplicate standard output\n");
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return -1;
}
//restores fd1
if(dup2(fd1, STDOUT_FILENO) < 0){
printf("Error: Failed to duplicate the file \"%s\" to standard output\n", fileName);
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return -1;
}
close(fd1);
return fd2;
}
void stdoutToNormal(int fd2){
fflush(stdout); //safety precaution
//restores fd2
if(dup2(fd2, STDOUT_FILENO) < 0){
printf("Error: Failed to reinstate standard output\n");
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return;
}
close(fd2);
}
//redirects stdout to newly created file "fileName," catering for symbol '>'
void redirectOutput(char * cmd[MAX_ARGS], char * fileName, int flag){
/* Connect standard output to given file*/
int fd2 = stdoutToFile(fileName, flag);
/* Write to standard output */
checkCmd(cmd); //checks command type, then parses and executes
/* Reconnect original standard output */
stdoutToNormal(fd2);
}
//checks for input or output redirection
void checkInputOutput(char * args[MAX_ARGS]){
char * cmd[MAX_ARGS] = {NULL}; //stores command
int flag = 0; //initialized flag, changes when > or >> is detected
int i; //initialized counter for for loop
//traverses through arguments looking for redirection symbols
for(i = 0; flag == 0 && args[i] != NULL; i++){
//match found with >
if(strcmp(args[i], ">") == 0) flag = 1;
//match found with >>
else if(strcmp(args[i], ">>") == 0) flag = 2;
//match found with <
else if(strcmp(args[i], "<") == 0) flag = 3;
//match found with <<
else if(strcmp(args[i], "<<<") == 0) flag = 4;
//argument is not a I/O redirection symbol
else cmd[i] = args[i];
}
//if more than one argument after > or >> is found, return an error and stop
if( (flag == 1 || flag == 2) && args[i+1] != NULL){
printf("Error: Please enter a single file name argument for output redirection\n");
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return;
}
//if more than one argument after <, return an error and stop
else if( (flag == 3) && args[i+1] != NULL){
printf("Error: Please enter a single file name argument for input redirection\n");
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return;
}
/* When redirection is flagged*/
if(flag != 0){
//if output redirection is detected
if(flag == 1 || flag == 2) redirectOutput(cmd, args[i], flag);
//file input redirection '<' is detected
else if(flag == 3) redirectInputFile(cmd, args[i]);
//string input redirection '<<<' is detected (flag == 4)
else{
char * stringArray[MAX_ARGS]; //makes string array for string after "<<<"
for(int j = 0; args[i] != NULL; j++){
stringArray[j] = args[i]; //puts all contents into stringArray
i++;
}
stringArray[i] = NULL; //sets last token to null
redirectInputString(cmd, stringArray);
}
}
/* When no redirection is flagged*/
//if no output redirection is detected
else checkCmd(cmd); //parses through command normally with stdout
}