-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvrblController.c
More file actions
245 lines (147 loc) · 7.57 KB
/
vrblController.c
File metadata and controls
245 lines (147 loc) · 7.57 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
#include "eggshell.h"
/* Struct declarations */
//struct for storing shellVariable with it's string name and string values
typedef struct shellVariable {
char * name; //stores the variable name
char * value; //stores the variable value
} Var;
//struct for a dynamic array called VariableArray that points to ShellVariables
typedef struct variableArray {
Var ** varArr; //double pointer to act as an array of structs
int amount; //stores amount of variables in array, increases array dynamically
} VarArr;
/* Global variables */
VarArr * variables; //dynamic array that stores variables
//validates variable name for containing (a-z, A-Z), (0-9) or (_), returns 0 when succeeded, -1 when failed
int validateVarName(char * name) {
char tempName[strlen(name)]; //temporarily stores name for character scanning
strcpy(tempName, name); //copies String pointer name into String array tempName
//scan every character in string name of variable
for (int i = 0; i < strlen(name); i++) {
//if character is not a digit or letter and is not an underscore
if (!isalnum(tempName[i]) && tempName[i] != '_') {
return -1; //return -1, indicating the name failed validation
}
}
return 0; //return 0, indicating it checked every character, proved valid
}
//returns value content from variable name if exists, if doesn't returns NULL
char * getVarValue(const char * varName){
varName+=1; //points to string after '$', so it can compare the name
//traverses through variable array searching for a variable name match
for(int i = 0; i < variables->amount; i++ ){
//if a match is found
if(strcmp(variables->varArr[i]->name,varName) == 0){
return variables->varArr[i]->value; //return value when match is found
}
}
printf("Error: Requested Shell Variable not found.\n");
addVar("EXITCODE","404"); //exit code to -1, as error occurred
return "(null)"; //return null string when no match is found (variable doesn't exist)
}
//gets the index of a variable in the dynamic array by name
int getVarIndex(const char * varName){
//traverses through variable array searching for a variable name match
for(int i = 0; i < variables->amount; i++ ){
//if a match is found
if(strcmp(variables->varArr[i]->name,varName) == 0){
return i; //return index when match is found
}
}
return -1; //return -1 when no match is found (variable doesn't exist)
}
//method used for adding a shell variable and storing to a dynamic array of structs if doesn't already exist
void addVar(char * name, char * value) {
if (validateVarName(name) != 0) { //used to catch just in case the variable name is not valid
printf("Error: Variable \"%s\" should contain digits, letters and underscores only. Please try again.\n", name);
addVar("EXITCODE","-1"); //exit code to -1, as error occurred
return; //returns, to cancel adding variable
}
int v = variables->amount; //sets variable index v to the amount of variables stores
//if at variable after the first entry
if(v >= 1){
int i = getVarIndex(name); //i becomes the index of varName if exists, -1 if doesn't exist
//check if variable name is already stored in the variable storage
if(i != -1){
variables->varArr[i]->value = value; //since already stored just overwrites previous value with new one
return; //returns to avoid unnecessary memory allocating
}else{
//dynamically increases the varArr by one as adding a new variable
variables->varArr = (Var **) realloc(variables->varArr, sizeof(Var) * v);
}
}
variables->varArr[v] = malloc(sizeof(Var)); //allocates memory for new variable in varArr[v]
variables->varArr[v]->name = name; //sets name at index v
variables->varArr[v]->value = value; //sets value at index v
variables->amount++; //increases amount by 1
}
//method that sets the variable CWD for current working directory (used when resetting)
void setCWD(void){
char buffer[MAX_CHAR];//sets buffer with max character length for string
char * cwd; //pointer to point to this String array buffer
getcwd(buffer, sizeof(buffer)); //gets initial current working directory
cwd = strdup(buffer); //allocates memory for cwd, by using buffer as a source
addVar("CWD", cwd); //adds variable
}
//sets the variable PROMPT by concatenating CWD to EggShell string and then adding $
void setPROMPT(void){
char buffer[MAX_CHAR] = ""; //buffer declared for strcat
char * eggString = "eggShell-lineInput";
char * prompt; //initialized
strcat(buffer, getVarValue("$USER")); //concat user name
strcat(buffer, "@");
strcat(buffer, eggString); //concat egg shell name
strcat(buffer, "~");
strcat(buffer, getVarValue("$CWD")); //concat current working directory
strcat(buffer, "$> ");
prompt = strdup(buffer); //allocates memory for prompt, by using buffer as a source
addVar("PROMPT", prompt); //adds variable
}
//sets the variable SHELL (Shell Variable) as path to currently executed binary file
void setSV(void){
char pathString[MAX_CHAR]; //initialized for readlink use
char * path = malloc(MAX_CHAR * sizeof(char)); //mallocs to avoid data corruption, imp as used for chdir
pid_t pid = getpid(); //gets current process id to create pathString
sprintf(pathString, "/proc/%d/exe", pid); //creates pathString for readlink()
readlink(pathString, path, MAX_CHAR); //gets the path to executable and stores in path
addVar("SHELL", path); //adds variable
}
//sets specific shell variables
void setShellSpecific(void){
setSV(); //sets the path to binary file and adds as variable
setCWD(); //current working directory, accessed by chdir and used in PROMPT
setPROMPT(); //command prompt variable, to be used in cmdController.c
addVar("TERMINAL", ttyname(STDIN_FILENO)); //current terminal name
}
//initializes storage platform "variables" and adds initial shell variables to storage
void initShellVariables(void) {
//allocates memory for Variables Array which is just one item
variables = malloc(sizeof(VarArr));
//initializes variable amount with starting size 0, dynamically grows when adding variables
variables->amount = 0;
//allocating memory
variables->varArr = calloc(1, sizeof(Var)); //initially allocates memory for 1 var in varArr
/* Adding initial Shell Variables */
//adding error code variable
addVar("EXITCODE","(null)"); //initial exitcode variable
//adding getenv() variables
addVar("PATH", getenv("PATH")); //path to external commands
addVar("USER", getenv("USER")); //name of current user, used in PROMPT
addVar("HOME", getenv("HOME")); //home directory of user
//adding shell specific variables $CWD, $PROMPT, $SHELL and $TERMINAL
setShellSpecific(); //sets and adds them
}
//prints all the variables stored in the shell
void printAllVar(void){
printf("\n"); //skips a line beforeexit printing all
//traverses through storage of variables, printing out each one
for(int i = 0; i < variables->amount; i++ ){
printf("%s=%s\n", variables->varArr[i]->name, variables->varArr[i]->value);
}
printf("\n"); //skips a line after printing all
addVar("EXITCODE","0"); //reaches here when program executes command successfully, therefore stores 0 as EXITCODE
}
//frees all the variables stored in the shell by freeing dynamic array
void freeAllVar(void){
free(variables); //frees all variables and dynamic array that stores them
}