-
Notifications
You must be signed in to change notification settings - Fork 0
/
cmdInterpreter.c
280 lines (231 loc) · 7.1 KB
/
cmdInterpreter.c
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
279
/* Command Interpreter */
/* Includes */
#include <sys/ipc.h> // Interprocess Comunication
#include <sys/shm.h> // Shared Memory
#include <errno.h> // Error
#include <sys/stat.h> // Stat Definitions
#include <string.h> // String
#include <sys/wait.h> // Waitpid
#include <stdio.h> // Input and Output
#include <stdlib.h> // Library Definitions
#include <unistd.h> // Symbolic Constants and Types
#include <sys/types.h> // Types Definition
#include "errorControl.h" // Error Control Definitions
#define parametersMAX 100 // Define max number of parameters
enum returnConditions
{
exitProgram = 0,
userProgram = 1,
parametersExceeded = 2,
blank = 3,
ok = 4,
invalidCommand = 5
};
typedef enum returnConditions returnCond; // Return conditions
void clearArguments(int* argc, char** argv); // Clear arguments counter (ARGC) and arguments vector (ARGV)
returnCond interpretCmd (char* cmd, int* argc, char **argv); // Command interpreter function
void tryAgain (); // Invalid command
int main(int argc, char * argv[])
{
// Declarations
char * scheduler_args[1] = { NULL } ;
pid_t pid_cmdInterpreter, pid_scheduler;
int status;
pid_cmdInterpreter = getpid();
pid_scheduler = fork(); // Create a new process to execute scheduler
if (pid_scheduler > 0) // Interpreter Process
{
// Declarations
int shmArea_programIdentifier;
int shmSize_programIdentifier = 400*sizeof(char);
key_t key_programIdentifier = 8180;
char* programIdentifier;
int shmArea_schedulerStatus;
int shmSize_schedulerStatus = sizeof(int);
key_t key_scheduler = 8181;
int* schedulerStatus;
int i;
int errorControl;
char cmd[30];
returnCond state = ok;
int ARGC;
char **ARGV;
// Initializations
ARGV = (char**) malloc (parametersMAX*sizeof(char*));
if(ARGV == NULL) // Fail verification
{
printf("\nmalloc error\n");
exit(1);
}
// Program Identifier - Shared Memory - GET
shmArea_programIdentifier = shmget( /* key */ key_programIdentifier, /* size */ shmSize_programIdentifier, /* flags */ IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
failVerification(shmArea_programIdentifier, shm_get);
// Scheduler - Shared Memory - GET
shmArea_schedulerStatus = shmget( /* key */ key_scheduler, /* size */ shmSize_schedulerStatus, /* flags */ IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
failVerification(shmArea_schedulerStatus, shm_get);
// Program Identifier - Shared Memory - ATTACH
programIdentifier = (char*) shmat( /* shared memory identifier */ shmArea_programIdentifier, /* shared memory adress */ NULL, /* flags */ 0);
if(programIdentifier == (char*) -1) { errorControl = -1; }
failVerification(errorControl , shm_at);
// Scheduler - Shared Memory - ATTACH
schedulerStatus = (int*) shmat( /* shared memory identifier */ shmArea_schedulerStatus, /* shared memory adress */ NULL, /* flags */ 0);
if(schedulerStatus == (int*) -1) { errorControl = -1; }
failVerification(errorControl , shm_at);
// Command Interpreter
printf("\n***Command Interpreter start***\n");
*schedulerStatus = 1; // Set scheduler status to continue
while(state != exitProgram) // While dont exit
{
//printf("\n> "); // Wait for command
fflush(stdin);
gets(cmd); // Get command
state = interpretCmd (cmd, &ARGC, ARGV); // Interpret command
if(state == userProgram) // Command: Execute user program
{
// Send new program identification to scheduler
strcpy(cmd, ARGV[1]);
for(i = 2; i < ARGC; i++)
{
strcat(cmd, "#");
strcat(cmd, ARGV[i]);
}
strcpy(programIdentifier, cmd); // New process in shared memory
kill(pid_scheduler, SIGUSR1); // Warn scheduler
while(programIdentifier[0] != '\0') { } // Wait for process finish creation
}
else
{
if(state == exitProgram) // Command: Exit
{
*schedulerStatus = 0; // Set scheduler status to exit
}
}
}
// Finalizations
*schedulerStatus = 0; // Set scheduler status to exit
waitpid(pid_scheduler, NULL, 0); // Wait for scheduler to end
errorControl = shmdt( /* adress */ programIdentifier); // Program Identifier - Shared Memory - DEATTACH
failVerification(errorControl, shm_dt);
errorControl = shmdt( /* adress */ schedulerStatus); // Scheduler Status - Shared Memory - DEATTACH
failVerification(errorControl, shm_dt);
printf("\n***Command Interpreter end***\n");
_exit(1); // Leave
}
else
{
if (pid_scheduler == 0) // Scheduler Process
{
pid_scheduler = getpid();
printf("\n***Scheduler start***\n\n");
execve( "./scheduler", scheduler_args, NULL); // Execute scheduler process
perror("execve failed");
}
else // Fork failed
{
perror("fork failed");
_exit(1); // Leave
}
}
return 0;
}
/* Auxiliar Functions */
void clearArguments(int* argc, char** argv) // Clear argc and argv
{
int i;
*argc = 0; // Reset arguments count
for(i = 0; i < parametersMAX; i++) // Reset arguments vector
{
argv[i] = NULL;
}
}
returnCond interpretCmd (char* cmd, int* argc, char **argv) // Command interpreter function
{
int i, j, start = 0, end = 0;
int number;
clearArguments(argc, argv);
if(strcmp(cmd, "exit") == 0) // Exit command
{
return exitProgram;
}
// User program
for(i = 0; i <= strlen(cmd); i++) // Read command line
{
if(cmd[i] == ' ' || cmd[i] == '(' || cmd[i] == ')' || cmd[i] == ',' || cmd[i] == '\0')
{
if(end - start > 0)
{
//printf("start = %d \t end = %d\n", start, end);
if(*argc + 1 > parametersMAX)
{
// Parameters verification
clearArguments(argc, argv);
printf("\nWARNING: PARAMETERSMAX ERROR\n--- number of arguments exceeded\n\n");
return parametersExceeded;
}
argv[*argc] = (char*) malloc ((end - start + 1)*sizeof(char));
if(argv[*argc] == NULL)
{
printf("\nmalloc error\n");
exit(1);
}
// Save argument in argv
strncpy ( /* destination */ argv[*argc], /* source + beginIndex */ cmd + start, /* endIndex - beginIndex */ end - start);
*argc += 1; // Update argc count
start = i + 1;
}
else
{
if((i + 1) > strlen(cmd))
{
start = i;
}
else
{
start = i + 1;
}
}
}
else
{
if((i + 1) > strlen(cmd))
{
end = i;
}
else
{
end = i + 1;
}
}
}
// Final verifications
if(*argc < 3)
{
tryAgain();
return invalidCommand;
}
if(strcmp(argv[0], "exec") != 0)
{
tryAgain();
return invalidCommand;
}
if(strcmp(argv[1], "userProgram") != 0)
{
tryAgain();
return invalidCommand;
}
for(i = 2; i < *argc; i++)
{
number = atoi(argv[i]);
if(number == 0)
{
printf("ERROR: Program dont accept zero as argument\n");
tryAgain();
return invalidCommand;
}
}
return userProgram;
}
void tryAgain () // Invalid command
{
printf("Invalid command, please try again with:\nexec *program_name* *arguments*\nexit\n");
}