- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshell.c
More file actions
Latest commit
240 lines (211 loc) · 8.6 KB
/
Copy pathshell.c
File metadata and controls
240 lines (211 loc) · 8.6 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
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<dirent.h>
#include<fcntl.h>
#include<sys/stat.h>
// Header files for commands defined manually
#include"gls.h"
#include"gcd.h"
#include"ggrep.h"
#include"gcat.h"
#include"gmv.h"
#include"gpwd.h"
#include"gcp.h"
#include"gmkdir.h"
// sentence_size == size of the command one user can enter (Global)
// separator is used in string tokienization (Global)
#definesentence_size 1024
#defineseparator " \t\r\n\a&"
// Functions defined for user commands
intgcd(char**args);
inthelp(char**args);
intgexit(char**args);
intggrep(char**args);
intgls(char**args);
intgcat(char**args);
intgmv(char**args);
intgpwd(char**args);
intgrm(char**args);
intgcp(char**args);
intgmkdir(char**args);
// Information helper function for user using this Terminal accessible using help command
inthelp(char**args)
{
inti;
system("clear");
printf("\nThis is a Custom Shell written in C programming Language\n\n");
printf("Custom Commands added - gcat, gcd, ggrep, gls, gmv, gcp, gpwd, gmkdir.\n\n");
printf("All Custom Commands are simple ones ex. gcat is a simpler version of cat and lly for other cmds.\n\n");
printf("\n--------------------Have Fun--------------------\n\n");
return1;
}
// exit command used for leaving the terminal process
intgexit(char**args)
{
printf("Exiting.........\n");
exit(EXIT_SUCCESS);
return0;
}
/* Arguments list which are defined manually(means no builtins)..... (Global)
All commands working is the simple case working of different terminal commands
For ex. ggrep == grep, gcd == cd, gls == ls, gmv == mv...etc
*/
char*myArgs_list[] = {
"help",
"gexit",
"gmkdir",
"gcd",
"gls",
"gmv",
"ggrep",
"gcat",
"gcp",
"gpwd"
};
// Manually defined arguments list length (Global)
intmyArgs_list_size=sizeof(myArgs_list)/sizeof(char*);
// function to tokenize or split the sentence into its words or equivalently command into arguments.
// Parameter sentence is accepted from the user using fgets() in main().
char**split_sentence(char*sentence){
char**args_list=malloc(sentence_size*sizeof(char*)); // Defining argument character array with column 1024 with each box of bits equal to bits of char
char*token; // word or token extracted from the sentence or command
intindex=0; // index for storing the tokens in args_list
if(!args_list){ // Failure in the Memory allocation of args_list
fprintf(stderr,"Memory allocation Failed\n");
exit(EXIT_FAILURE); // exit(EXIT_FAILURE) ensures the termination of the process
}
token=strtok(sentence,separator); // strtok() accepts the string with the delimiters on basis of which the command to be splitted into words
// strtok() returns a pointer to the next token and NULL if no token exsist.
while(token!=NULL){ // Checking if the tokens are finished or not in the string
args_list[index] =token; // stroing the tokens in the args_list
index++; // incrementing index to store unique tokens in unique places in the args_list
token=strtok(NULL,separator); // Take pointer to the next token
}
args_list[index]=NULL; // Stroing NULL at the last
returnargs_list; // Complete args_list with all arguments
}
intbuiltin(char**args) // Builtin function to run commands which are not defined by the user
{
intrc,wait; //rc flag to ensure the creation of child process, wait flag for storing the successful run of child as child pid or an error as -1
intstatus; // ensure that the command is ran successfully with no error and carry on the loop in main() using this status
rc=fork(); // creating Parent and Child Processes
if(rc<0){ // child not created
fprintf(stderr,"FORK NOT WORKING\n");
}
elseif(rc==0){ // Child process
/*
execvp() -- second argument is an array of null-terminated strings that represent
the appropriate arguments to the file as specified in the man page.
executing the builtin command args[0] represent the file you want to execute
*/
if(execvp(args[0],args)==-1){
fprintf(stderr,"Enter the correct command\n");
}
}else{
do{
wait=waitpid(rc, &status, WUNTRACED); // wait() command waits for the process to change the state
}while(!WIFEXITED(status) && !WIFSIGNALED(status));
// WIFEXITED returns true if the child terminated normally.
// WIFSIGNALED returns true if the child process was terminated by a signal.
// WUNTRACED also return if a child has stopped.
}
return1; // Indicates the successful running of the command and allowing loop in main to carry further commands
}
// Function which either run defined commands or the builtin command
// Parameter accepted is args which came from the splitting function split_sentence()
intredirect(char**args){
if(args[0] ==NULL){
return1;
} // If no command is entered and user press simply enter then status == 1 retured, to continue the loop in main()
for(inti=0;i<myArgs_list_size;i++)
{
/*Checking if the entered command argument matches with the argument defined
If yes, then run the user defined command defined in myArgsList[]
If not, then run builtin binary commands defined.
*/
if(strcmp(args[0],myArgs_list[i])==0){ //Commands comparison using stringCompare strcmp()
switch (i)
{
case0:
returnhelp(args);
case1:
returngexit(args);
case2:
returngmkdir(args);
case3:
returngcd(args);
case4:
returngls(args);
case5:
returngmv(args);
case6:
returnggrep(args);
case7:
returngcat(args);
case8:
returngcp(args);
case9:
returngpwd(args);
default:
break;
}
}
}
returnbuiltin(args); // If no command matches then run the builtin command
}
intcheck_chracter(char*input){
char*output=NULL;
output=strrchr(input, '&');
if(output!=NULL){
return1;
}
return0;
}
intmain(intargc, charconst*argv[])
{
/*Loop which continues and waiting for
command to enter and can be
terminated by using exit command (defined above)
or ctrl+C keyboard intterupt
*/
system("clear"); // Used to clear the terminal screen
printf("--Welcome to Lovepreet's Shell--\n\n");
char**args; // Used to store the arguments splitted from the command entered in the terminal
intn_args; // Number of arguments or words splitted
intstatus; // Status of command whether ran correct or not
char*sentence=malloc(sentence_size); // stores the input from the user entered in the terminal
do{
chardir[500]; // Character array defined to store the current directory
ssize_tsize=500; // size command for the getcwd()
getcwd(dir, size); // Storing the current working directory into dir char array of size 500
printf("%s > ", dir); // Print the current directory on the terminal
fgets(sentence,sentence_size,stdin);// Read the input from the terminal entered by the user
intflag=check_chracter(sentence); // Check if & is present or not to run commands in background
// printf("Flag : %d\n", flag);
if(flag){
intrc=fork();
if(rc<0){ // Child creation Failed
perror("Fork Failed\n");
}
elseif(rc==0){ // Child process
args=split_sentence(sentence); // splitting the sentence entered by the user.
n_args=sizeof(args)/sizeof(char); // Number of tokens splitted from the whole inputted command
status=redirect(args); // redirect to a function which will run either a command defined or a builtin binary command
free(args);
}
else{
status=1;
continue;
}
}else{ // Process running not in background
args=split_sentence(sentence); // splitting the sentence entered by the user.
n_args=sizeof(args)/sizeof(char); // Number of tokens splitted from the whole inputted command
status=redirect(args); // redirect to a function which will run either a command defined or a builtin binary command
free(args); // Memory free from the storage of the earlier entered arguments
}
}while(status); // Make the loop running until error doesn't occur (fork failed or memory allocation error) or process not interrupted
return0;
}