Shell
Shell
c
2 //UISH (University of Idaho Shell)
3 //CS 240 Assignment 4 by Carson Gustavel
4
5 #include<stdio.h>
6 #include<stdlib.h>
7 #include <ctype.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/wait.h>
11 #include <string.h>
12
13 int makearg(char *s, char ***args);
14 int makepath(char *s, char ***args);
15 void runExec( char**, int , char* );
16
17 int main(){
18
19 int cont = 1; //when zero, close down shell
20
21 //get path, make path vector:
22 char* path = getenv( "PATH" );
23 //printf( "Path: %s\n" , path );
24 char** pathv;
25 int pathc = makepath( path , &pathv );
26 /*
27 for( int i = 0; i < pathc; i++ ){
28 printf("|%s|\n", pathv[i]);
29 }
30 */
31
32 //shell variables storage:
33 char** variableNames;
34 char** variableContents;
35 int variableNum = 0;
36 variableNames = (char**)malloc( 256 * sizeof(char*));
37 variableContents = (char**)malloc( 256 * sizeof(char*));
38
39
40 while( cont ){ //main loop
41
42 int bg = 0; //run command in background?
43
44 printf( "$ " );
45
46 //get user input
47 char input[1024];
48 fgets( input , 1024 , stdin );
49
50 //process user input:
51 char **argv;
52 int argc = makearg( input , &argv );
53 //run in background?
54 for ( int i = 0; i < argc ; i++ ){
55 if ( strcmp ( argv[i] , "&" ) == 0 && ( argv[i+1] == NULL ) ){
56 // printf("Running in background\n");
57 bg = 1;
58 argv[i] = NULL;
59 }
60 }
61 //is command trying to create a shell variable?
62 if ( argc == 1 ){
63 int seperatorIndex = 0;
64 for ( int i = 0; argv[0][i] != '\0' ; i++ ){
65 if ( argv[0][i] == '=' ){
66 seperatorIndex = i;
67 break;
68 }
69 }
70 if ( seperatorIndex == 0 ) {
71
72 } else {
73 //does it already exist?
74 //printf("Checking if variable already exists:\n");
75 int exists = 0;
76 char temp[seperatorIndex];
77 for ( int i = 0; i < seperatorIndex ; i++ ){
78 temp[i] = argv[0][i];
79 }
80 temp[seperatorIndex] = '\0';
81 if ( variableNum > 0 ){
82 //printf("Does the shell variable |%s| already exist?\n" , temp);
83 for ( int i = 0; i < variableNum ; i++ ){
84 //printf("|\n");
85 if ( strcmp( temp , variableNames[i] ) == 0 ){
86 exists = i+1;
87 //printf("Variable Exists at index %d\n" , exists-1);
88 }
89 }
90 }
91 if ( exists ){ //if it exists already:
92 //printf( "Variable |%s|, already exists at index |%d|\n" , temp ,
exists-1);
93 exists--;
94 free ( variableContents[exists] );
95 variableContents[exists] = (char*)malloc( ( strlen( argv[0] ) -
seperatorIndex + 1 ) * sizeof(char) );
96 int counter = 0;
97 for ( int i = seperatorIndex + 1; i < strlen( argv[0] ) ; i++ ){
98 variableContents[exists][counter] = argv[0][i];
99 counter++;
100 }
101 variableContents[exists][strlen( argv[0] ) - seperatorIndex - 1] = '\0';
102 } else { //create new shell var:
103 //printf( "Variable |%s|, does not exists, creating at index |%d|\n" ,
temp , variableNum );
104 //printf( "Seperator Index: %d\n" , seperatorIndex );
105 variableNames[variableNum] = (char*)malloc( ( seperatorIndex + 1 ) * sizeof
(char) );
106 //printf("|");
107 variableContents[variableNum] = (char*)malloc( ( strlen( argv[0] ) -
seperatorIndex + 1 ) * sizeof(char) );
108 //printf("Filling in variable name\n");
109 for ( int i = 0; i < seperatorIndex; i++ ){
110 variableNames[variableNum][i] = argv[0][i];
111 }
112 variableNames[variableNum][seperatorIndex] = '\0';
113
114 //printf("Filling in variable contents\n");
115 int counter = 0;
116 for ( int i = seperatorIndex+1; i < strlen( argv[0] ) ; i++ ){
117 variableContents[variableNum][counter] = argv[0][i];
118 counter++;
119 }
120 variableContents[variableNum][strlen( argv[0] ) - seperatorIndex] = '\0';
121
122 variableNum++;
123 }
124 }
125 }
126 //is command trying to read a path variable?
127 if ( variableNum > 0 ){
128 for ( int i = 0; i < argc; i++ ){
129 if ( argv[i][0] == '$' ){
130 //printf( "Shell Variable %s Detected\n" , argv[i] );
131 char temp[strlen( argv[i] )];
132 for ( int j = 0; j < strlen(argv[i]) ; j++ ){
133 temp[j] = argv[i][j+1];
134 }
135
136 //printf( "Comparing value: |%s|\n" , temp );
137 for ( int j = 0; j < variableNum; j++ ){
138 if ( strcmp( temp , variableNames[j] ) == 0 ){
139 //printf( "Replacing |%s| with |%s|\n" , argv[i] ,
variableContents[j] );
140 free( argv[i] );
141 argv[i] = (char*)malloc( ( strlen( variableContents[j] ) + 1 ) *
sizeof(char) );
142 strncpy( argv[i] , variableContents[j] , strlen(variableContents[j])
+ 1 );
143 argv[i][strlen(variableContents[j])] = '\0';
144 }
145 }
146 }
147 }
148 }
149
150 //run command:
151 pid_t p = fork();
152
153 if( p != 0 ){ //I am a parent
154 //parenting stuff
155 } else { //I am a child
156 //child stuff:
157 //run exec
158 // int error = execvp( argv[0] , argv);
159 for ( int i = 0; i < pathc; i++ ){
160 runExec( argv , argc , pathv[i] );
161 }
162 // printf("\n-uish: Command not found\n$ ", input);
163 exit(0);
164 }
165
166 //run in background?
167 if ( bg == 0 ){
168 wait( NULL );
169 } else {
170 //run in background
171 }
172
173 //clear memory for argv:
174 // printf("Freeing Argv");
175 for (int i = 0; i < argc; i++) {
176 free(argv[i]);
177 }
178 free(argv);
179
180 }
181
182 //printf("Freeing pathv");
183 //clear memory for argv:
184 for (int i = 0; i < pathc; i++) {
185 free(pathv[i]);
186 }
187 free(pathv);
188
189 //clear memory for variableNames:
190 for (int i = 0; i < variableNum; i++) {
191 free(variableNames[i]);
192 }
193 free(variableNames);
194 //clear memory for variableContents:
195 for (int i = 0; i < variableNum; i++) {
196 free(variableContents[i]);
197 }
198 free(variableContents);
199
200 }
201
202 //makearg
203 //Takes a character array (string) and an empty triple character pointer,
204 //tokenizes the string,
205 //storing it as a 2d array of characters inside of the pointer,
206 //memory will be dynamically declared to store the values
207 //returns the number of tokens in the array as an integer
208 int makearg(char *s, char ***args){
209
210 int argc = 0; //
211
212 int k = 0; //counter
213 while ( s[k] != '\0' ) { //loop until end of string, inclusive of \0 terminator
214 if ( s[k] == ' ' ){
215 argc++;
216 }
217 k++;
218 }
219 argc++;
220
221 // printf("There are %d arguments\n", argc);
222
223 *args = (char**)malloc( (argc + 1) * sizeof(char*));
224 // printf("Memory for args allocated\n");
225 //String counters:
226 int counter = 0;
227 int bookmark = 0;
228
229 for ( int currentArg = 0; currentArg < argc ; currentArg++ ){ //for each argument
230 // printf( "Scanning argument #%d\n" , currentArg );
231 while( !isspace(s[counter]) && s[counter] != '\0' ){
232 // printf("Scanning character #%d\n" , counter );
233 counter++;
234 }
235 if ( s[counter] != '\0') {
236 counter++;
237 }
238 // printf( "Token #%d is %d characters long\n" , currentArg , (counter - bookmark)
);
239 // printf( "It starts at index %d, and ends at index %d\n", bookmark, counter );
240 (*args)[currentArg] = (char*)malloc( ( counter - bookmark + 1 ) * sizeof(char) );
241 memset((*args)[currentArg], '\0', ( counter - bookmark + 1 ) * sizeof(char));
242 // printf("Memory for arg #%d allocated\n" , currentArg );
243 for ( int i = 0; i < ( counter - bookmark ); i++ ){
244 if (s[bookmark + i] == ' ' || s[bookmark + i] == '\n' ) {
245 continue;
246 } //strip white space
247 (*args)[currentArg][i] = s[ bookmark + i ];
248 // printf( "Copying character %c\n" , s[ bookmark + i ] );
249 // printf( "Successfully copied %c\n" , (*args)[currentArg][i] );
250 }
251 //strncpy ( (*args)[currentArg] , &s[bookmark], counter-bookmark-1 );
252 // printf("done with tranfering #%d\n", currentArg);
253 (*args)[currentArg][counter-bookmark] = '\0'; //ensure the final index has a null
terminator
254 bookmark = counter;
255 }
256
257 return argc;
258
259 }
260
261 //makearg
262 //Takes a character array (string) and an empty triple character pointer,
263 //tokenizes the string,
264 //storing it as a 2d array of characters inside of the pointer,
265 //memory will be dynamically declared to store the values
266 //returns the number of tokens in the array as an integer
267 int makepath(char *s, char ***args){
268
269 int argc = 0; //
270
271 int k = 0; //counter
272 while ( s[k] != '\0' ) { //loop until end of string, inclusive of \0 terminator
273 if ( s[k] == ':' ){
274 argc++;
275 }
276 k++;
277 }
278 argc++;
279
280 // printf("There are %d arguments\n", argc);
281
282 *args = (char**)malloc( (argc + 1) * sizeof(char*));
283 // printf("Memory for args allocated\n");
284 //String counters:
285 int counter = 0;
286 int bookmark = 0;
287
288 for ( int currentArg = 0; currentArg < argc ; currentArg++ ){ //for each argument
289 // printf( "Scanning argument #%d\n" , currentArg );
290 while( s[counter] != ':' && s[counter] != '\0' ){
291 // printf("Scanning character #%d\n" , counter );
292 counter++;
293 }
294 if ( s[counter] != '\0') {
295 counter++;
296 }
297 // printf( "Token #%d is %d characters long\n" , currentArg , (counter - bookmark)
);
298 // printf( "It starts at index %d, and ends at index %d\n", bookmark, counter );
299 (*args)[currentArg] = (char*)malloc( ( counter - bookmark + 1 ) * sizeof(char) );
300 memset((*args)[currentArg], '\0', ( counter - bookmark + 1 ) * sizeof(char));
301 // printf("Memory for arg #%d allocated\n" , currentArg );
302 for ( int i = 0; i < ( counter - bookmark ); i++ ){
303 if (s[bookmark + i] == ':' || s[bookmark + i] == '\n') {
304 continue;
305 } //strip white space
306 (*args)[currentArg][i] = s[ bookmark + i ];
307 // printf( "Copying character %c\n" , s[ bookmark + i ] );
308 // printf( "Successfully copied %c\n" , (*args)[currentArg][i] );
309 }
310 //strncpy ( (*args)[currentArg] , &s[bookmark], counter-bookmark-1 );
311 // printf("done with tranfering #%d\n", currentArg);
312 (*args)[currentArg][counter-bookmark] = '\0'; //ensure the final index has a null
terminator
313 bookmark = counter;
314 }
315
316 return argc;
317
318 }
319
320 void runExec( char** argv , int argc , char* path ){
321
322 int n = strlen( argv[0] );
323 n += strlen(path);
324 n += 2;
325
326 char temp[n];
327 strncpy( temp , path , n );
328 strncat( temp , "/" , n );
329 strncat( temp , argv[0] , n );
330 temp[n-1] = '\0';
331 /*
332 printf( "Temp: |%s|" , temp );
333 for ( int i = 0; i < argc; i++ ){
334 printf( "Argv[%d]: |%s|\n" , i , argv[i] );
335 }
336 */
337 // printf("Attempting execv");
338 execv( temp , argv );
339 // printf("execv appears to have failed.");
340
341 return;
342
343 }
344