Created
October 20, 2015 12:52
-
-
Save siddharthg/ab2fa577d48f727a2a5a to your computer and use it in GitHub Desktop.
A small shell written in C.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
char * RemoveSpace(char *string);//To remove spaces in between file name. | |
void parse(char *cmd,char **argv);//to save the command line input into an array | |
void ExecuteDoublePipe(char **argv,char **args,char **argc);//Single function two execute three commands joined through pipes | |
void OutputInFile(char **argv, char *file);//Execute a command and save teh output in a file | |
void ExecutePipeToFile(char **argv, char **args, char *file);//Execute a pipe and save the output to file | |
void ExecutePipeFromFile(char **argv, char **args, char *file);//Execute a pipe and take the input from the file | |
void ExecuteSinglePipe(char **argv, char **args);//Execute two commands joined through Pipe | |
void ExecuteSingleCommand(char **argv);//ExecuteSingle Command | |
void InputFromFile(char **argv, char *file);//Execute a command taking input from the file | |
void InputFromFileOutputToFile(char **argv, char *input, char *output);//Execute a command taking input from a file and saving the output to a new file | |
void InputFromFileToPipe(char **argv, char *input, char **args);//Execute a commnd taking input from a file and send the output to a pipe to execute second command. | |
int main(){ | |
char *args[64], *argv[64], *argc[64]; | |
int count; | |
size_t size; | |
while(1) | |
{ | |
count=0;int Case=0; | |
printf("$!dd@rth!->~$!d~~~"); | |
char *cmd1=NULL, *cmd2=NULL, *cmd3=NULL; | |
int length=getline(&cmd1,&size,stdin); | |
cmd1[length-1]='\0'; | |
int i,j; | |
for(i=0;cmd1[i]!='\0';i++){ | |
if(cmd1[i]=='<') | |
{ | |
strtok_r(cmd1,"<",&cmd2); | |
if(strstr(cmd2,"|")){ | |
strtok_r(cmd2,"|",&cmd3); | |
Case=1; | |
} | |
else if(strstr(cmd2,"<")){ | |
strtok_r(cmd2,"<",&cmd3); | |
Case=2; | |
} | |
else if(strstr(cmd2,">")){ | |
strtok_r(cmd2,">",&cmd3); | |
Case=3; | |
} | |
else{ | |
Case=4; | |
} | |
break; | |
} | |
else if(cmd1[i]=='>') | |
{ | |
strtok_r(cmd1,">",&cmd2); | |
if(strstr(cmd2,"|")){ | |
strtok_r(cmd2,"|",&cmd3); | |
Case=5; | |
} | |
else if(strstr(cmd2,"<")){ | |
strtok_r(cmd2,"<",&cmd3); | |
Case=6; | |
} | |
else if(strstr(cmd2,">")){ | |
strtok_r(cmd2,">",&cmd3); | |
Case=7; | |
} | |
else{ | |
Case=8; | |
} | |
break; | |
} | |
else if(cmd1[i]=='|') | |
{ | |
strtok_r(cmd1,"|",&cmd2); | |
if(strstr(cmd2,"|")){ | |
strtok_r(cmd2,"|",&cmd3); | |
Case=9; | |
} | |
else if(strstr(cmd2,"<")){ | |
strtok_r(cmd2,"<",&cmd3); | |
Case=10; | |
} | |
else if(strstr(cmd2,">")){ | |
strtok_r(cmd2,">",&cmd3); | |
Case=11; | |
} | |
else{ | |
Case=12; | |
} | |
break; | |
} | |
else | |
Case=13; | |
} | |
//printf("%s %s %s ",cmd1,cmd2,cmd3); | |
//printf("\n",Case); | |
if(!strcmp(cmd1,"\0")){ | |
continue; | |
} | |
else if(!strcmp(cmd1,"exit")){ | |
exit(0); | |
} | |
switch(Case){ | |
case 1:{ | |
parse(cmd1,argv); | |
cmd2=RemoveSpace(cmd2); | |
parse(cmd3,args); | |
InputFromFileToPipe(argv,cmd2,args); | |
break; | |
} | |
case 2:{ | |
parse(cmd1,argv); | |
cmd2=RemoveSpace(cmd2); | |
cmd3=RemoveSpace(cmd3); | |
int fd = open(cmd2, O_RDONLY); | |
if(fd<0){ | |
printf("File does not exist"); | |
exit(0); | |
} | |
InputFromFile(argv,cmd3); | |
break; | |
} | |
case 3:{ | |
parse(cmd1,argv); | |
cmd2=RemoveSpace(cmd2); | |
cmd3=RemoveSpace(cmd3); | |
InputFromFileOutputToFile(argv,cmd2,cmd3); | |
break; | |
} | |
case 4:{ | |
parse(cmd1,argv); | |
cmd2=RemoveSpace(cmd2); | |
InputFromFile(argv,cmd2); | |
break; | |
} | |
case 5:{ | |
parse(cmd1,argv); | |
cmd2=RemoveSpace(cmd2); | |
parse(cmd3,args); | |
OutputInFile(argv,cmd2); | |
ExecuteSingleCommand(args); | |
break; | |
} | |
case 6:{ | |
parse(cmd1,argv); | |
cmd2=RemoveSpace(cmd2); | |
OutputInFile(argv,cmd2); | |
break; | |
} | |
case 7:{ | |
parse(cmd1,argv); | |
FILE *fp1= fopen(cmd2,"wb"); | |
fclose(fp1); | |
cmd3=RemoveSpace(cmd3); | |
OutputInFile(argv,cmd3); | |
break; | |
} | |
case 8:{ | |
parse(cmd1,argv); | |
cmd2=RemoveSpace(cmd2); | |
OutputInFile(argv,cmd2); | |
break; | |
} | |
case 9:{ | |
parse(cmd1,argv); | |
parse(cmd2,argc); | |
parse(cmd3,args); | |
ExecuteDoublePipe(argv,argc,args); | |
break; | |
} | |
case 10:{ | |
parse(cmd1,argv); | |
parse(cmd2,args); | |
cmd3=RemoveSpace(cmd3); | |
ExecutePipeFromFile(argv,args,cmd3); | |
break; | |
} | |
case 11:{ | |
parse(cmd1,argv); | |
parse(cmd2,args); | |
cmd3=RemoveSpace(cmd3); | |
ExecutePipeToFile(argv,args,cmd3); | |
break; | |
} | |
case 12:{ | |
parse(cmd1,argv); | |
parse(cmd2,args); | |
ExecuteSinglePipe(argv,args); | |
break; | |
} | |
case 13:{ | |
parse(cmd1,argv); | |
ExecuteSingleCommand(argv); | |
break; | |
} | |
default:{ | |
printf("This type of command is not supported in this cool shell!\n"); | |
break; | |
} | |
} | |
} | |
} | |
void ExecuteDoublePipe(char **argv,char **args,char **argc) | |
{ | |
int status; | |
int i; | |
int piped[4]; | |
pipe(piped); | |
pipe(piped + 2); | |
if (fork()==0) | |
{ | |
dup2(piped[1], 1); | |
close(piped[0]); | |
close(piped[1]); | |
close(piped[2]); | |
close(piped[3]); | |
if(execvp(argv[0],argv)<0){ | |
fflush(stdout); | |
printf("EXEC Failed"); | |
fflush(stdout); | |
close(piped[0]); | |
close(piped[1]); | |
close(piped[2]); | |
close(piped[3]); | |
exit(1); | |
} | |
} | |
else | |
{ | |
if (fork() == 0) | |
{ | |
dup2(piped[0], 0); | |
dup2(piped[3], 1); | |
close(piped[0]); | |
close(piped[1]); | |
close(piped[2]); | |
close(piped[3]); | |
if(execvp(args[0],args)<0){ | |
fflush(stdout); | |
printf("EXEC Failed"); | |
fflush(stdout); | |
close(piped[0]); | |
close(piped[1]); | |
close(piped[2]); | |
close(piped[3]); | |
exit(1); | |
} | |
} | |
else{ | |
if (fork() == 0) | |
{ | |
dup2(piped[2], 0); | |
close(piped[0]); | |
close(piped[1]); | |
close(piped[2]); | |
close(piped[3]); | |
if(execvp(argc[0],argc)<0){ | |
fflush(stdout); | |
printf("EXEC Failed"); | |
fflush(stdout); | |
close(piped[0]); | |
close(piped[1]); | |
close(piped[2]); | |
close(piped[3]); | |
exit(1); | |
} | |
} | |
} | |
} | |
close(piped[0]); | |
close(piped[1]); | |
close(piped[2]); | |
close(piped[3]); | |
for (i = 0; i < 3; i++) | |
wait(&status); | |
} | |
void OutputInFile(char **argv, char *file){ | |
pid_t ProcessID; | |
int status; | |
if ((ProcessID = fork()) < 0) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
else if (ProcessID == 0) { | |
int old_stdout = dup(1); | |
FILE *fp1= freopen(file,"a+",stdout); | |
if(execvp(argv[0],argv)<0)//{ | |
printf("EXEC Failed\n"); | |
fclose(stdout); | |
FILE *fp2 = fdopen(old_stdout, "w"); | |
*stdout = *fp2; | |
exit(0); | |
} | |
else{ | |
while (wait(&status) != ProcessID) ; | |
} | |
} | |
void InputFromFile(char **argv, char *file){ | |
pid_t ProcessID; | |
int fd; | |
int status; | |
if ((ProcessID = fork()) < 0) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
else if (ProcessID == 0) { | |
fd = open(file, O_RDONLY); | |
if(fd<0){ | |
printf("This File does not exist"); | |
exit(0); | |
} | |
close(0); | |
dup(fd); | |
if(execvp(argv[0],argv)<0){ | |
printf("EXEC Failed\n"); | |
} | |
close (fd); | |
exit(0); | |
} | |
else { | |
while (wait(&status) != ProcessID) ; | |
} | |
} | |
void ExecutePipeToFile(char **argv, char **args, char *file) | |
{ | |
int piped[2]; | |
pid_t ProcessID1,ProcessID2; | |
int status1,status2; | |
pipe(piped); | |
int old_stdout; | |
int flag=0; | |
if ((ProcessID1 = fork()) < 0) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
if ((ProcessID2 = fork()) < 0 ) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
if (ProcessID1==0 && ProcessID2!=0) { | |
close(1); | |
dup(piped[1]); | |
close(piped[0]); | |
close(piped[1]); | |
if(execvp(argv[0],argv)<0){ | |
close(piped[0]); | |
close(piped[1]); | |
printf("EXEC Failed"); | |
flag=1;exit(1); | |
} | |
} | |
else if(ProcessID2==0 && ProcessID1 !=0){ | |
if(flag==1){exit(0);} | |
close(0); | |
dup(piped[0]); | |
close(piped[1]); | |
close(piped[0]); | |
old_stdout = dup(1); | |
FILE *fp1= freopen(file,"a+",stdout); | |
if(execvp(args[0],args)<0){ | |
fflush(stdout); | |
printf("EXEC Failed \n"); | |
close(piped[0]); | |
close(piped[1]); | |
} | |
fclose(stdout); | |
FILE *fp2 = fdopen(old_stdout, "w"); | |
*stdout = *fp2; | |
} | |
else{ | |
close(piped[0]); | |
close(piped[1]); | |
while (wait(&status1) != ProcessID1) ; | |
while (wait(&status2) != ProcessID2) ; | |
} | |
} | |
void ExecutePipeFromFile(char **argv, char **args, char *file) | |
{ | |
int piped[2]; | |
pid_t ProcessID1,ProcessID2; | |
int status1,status2; | |
pipe(piped); | |
int old_stdout; | |
int flag=0; | |
if ((ProcessID1 = fork()) < 0) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
if ((ProcessID2 = fork()) < 0 ) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
if (ProcessID1==0 && ProcessID2!=0) { | |
close(1); | |
dup(piped[1]); | |
close(piped[0]); | |
close(piped[1]); | |
if(execvp(argv[0],argv)<0){ | |
close(piped[0]); | |
close(piped[1]); | |
printf("EXEC Failed\n"); | |
flag=1;exit(1); | |
} | |
} | |
else if(ProcessID2==0 && ProcessID1 !=0){ | |
if(flag==1){exit(0);} | |
InputFromFile(args,file); | |
close(piped[0]); | |
close(piped[1]); | |
exit(1); | |
} | |
else{ | |
close(piped[0]); | |
close(piped[1]); | |
while (wait(&status1) != ProcessID1) ; | |
while (wait(&status2) != ProcessID2) ; | |
} | |
} | |
void ExecuteSinglePipe(char **argv, char **args) | |
{ | |
int piped[2]; | |
pid_t ProcessID1,ProcessID2; | |
int status1,status2; | |
pipe(piped); | |
int flag=0; | |
if ((ProcessID1 = fork()) < 0) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
if ((ProcessID2 = fork()) < 0 ) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
if (ProcessID1==0 && ProcessID2!=0) { | |
close(1); | |
dup(piped[1]); | |
close(piped[0]); | |
close(piped[1]); | |
if(execvp(argv[0],argv)<0){ | |
close(piped[0]); | |
close(piped[1]); | |
printf("EXEC Failed \n"); | |
flag=1;exit(1); | |
} | |
} | |
else if(ProcessID2==0 && ProcessID1 !=0){ | |
if(flag==1){exit(0);} | |
close(0); | |
dup(piped[0]); | |
close(piped[1]); | |
close(piped[0]); | |
if(execvp(args[0],args)<0){ | |
fflush(stdout); | |
printf("EXEC Failed %d",ProcessID1); | |
close(piped[0]); | |
close(piped[1]); | |
} | |
} | |
else{ | |
close(piped[0]); | |
close(piped[1]); | |
while (wait(&status1) != ProcessID1) ; | |
while (wait(&status2) != ProcessID2) ; | |
} | |
} | |
char * RemoveSpace(char *string){ | |
int i,count=0; | |
char *newstring; | |
newstring=malloc(strlen(string)*sizeof(char)); | |
for(i=0;string[i]!='\0';i++){ | |
if(string[i]!=' '){ | |
newstring[count++]=string[i]; | |
} | |
} | |
newstring[count]='\0'; | |
string=newstring; | |
return string; | |
} | |
void parse(char *cmd,char **argv) | |
{ | |
int i=0; | |
if(strstr(cmd,"|")||strstr(cmd,"<")||strstr(cmd,">")) | |
{ | |
printf("This type of command is not supported in this cool shell!\n"); | |
} | |
memset(argv, 0, sizeof(char*) * (64)); | |
char *cmd1=NULL; | |
while(1==1) | |
{ | |
char *arg=strtok_r(cmd," ", &cmd1); | |
if(arg==NULL){ | |
break; | |
} | |
argv[i]=arg; | |
cmd=cmd1; | |
i++; | |
} | |
if (strcmp(argv[0],"exit") == 0) | |
exit(0); | |
else if(strcmp(argv[0],"cd")==0){ | |
chdir(argv[1]); | |
} | |
} | |
void ExecuteSingleCommand(char **argv) | |
{ | |
pid_t processID; | |
int CurrentStatus; | |
processID=fork(); | |
if(processID<0){ | |
printf("Fork Failed\n"); | |
} | |
if(processID==0){ | |
if(execvp(argv[0],argv)<0){ | |
printf("Exelcvp Failed\n"); | |
} | |
exit(0); | |
} | |
else | |
while(wait(&CurrentStatus)!=processID); | |
} | |
void InputFromFileOutputToFile(char **argv, char *input, char *output){ | |
pid_t ProcessID; | |
int fd; | |
int status; | |
if ((ProcessID = fork()) < 0) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
else if (ProcessID == 0) { | |
int old_stdout = dup(1); | |
FILE *fp1= freopen(output,"a+",stdout); | |
InputFromFile(argv,input); | |
fclose(stdout); | |
FILE *fp2 = fdopen(old_stdout, "w"); | |
*stdout = *fp2; | |
exit(0); | |
} | |
else { | |
while (wait(&status) != ProcessID) ; | |
} | |
} | |
void InputFromFileToPipe(char **argv, char *input, char **args){ | |
pid_t MainProcess; | |
int fd; | |
int status; | |
if ((MainProcess = fork()) < 0) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
else if (MainProcess== 0) { | |
int piped[2]; | |
pid_t ProcessID1,ProcessID2; | |
int status1,status2; | |
pipe(piped); | |
int flag=0; | |
if ((ProcessID1 = fork()) < 0) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
if ((ProcessID2 = fork()) < 0 ) { | |
printf("Fork Failed\n"); | |
exit(1); | |
} | |
if (ProcessID1==0 && ProcessID2!=0) { | |
close(1); | |
dup(piped[1]); | |
close(piped[0]); | |
close(piped[1]); | |
fd = open(input, O_RDONLY); | |
close(0); | |
dup(fd); | |
if(execvp(argv[0],argv)<0){ | |
close(piped[0]); | |
close(piped[1]); | |
printf("EXEC Failed"); | |
flag=1; | |
exit(0); | |
} | |
close (fd); | |
exit(0); | |
} | |
else if(ProcessID2==0 && ProcessID1 !=0){ | |
if(flag==1){exit(0);} | |
close(0); | |
dup(piped[0]); | |
close(piped[1]); | |
close(piped[0]); | |
if(execvp(args[0],args)<0){ | |
close(piped[0]); | |
close(piped[1]); | |
printf("EXEC Failed\n"); | |
exit(0); | |
} | |
} | |
else{ | |
close(piped[0]); | |
close(piped[1]); | |
while (wait(&status1) != ProcessID1) ; | |
while (wait(&status2) != ProcessID2) ; | |
} | |
exit(0); | |
} | |
else { | |
while (wait(&status) != MainProcess) ; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment