Skip to content

Instantly share code, notes, and snippets.

@siddharthg
Created October 20, 2015 12:52
Show Gist options
  • Save siddharthg/ab2fa577d48f727a2a5a to your computer and use it in GitHub Desktop.
Save siddharthg/ab2fa577d48f727a2a5a to your computer and use it in GitHub Desktop.
A small shell written in C.
#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