simple shell in C
This shell is called mosh (My Own Shell). When invoke, it should be able to read a command typed on its prompt ($) and execute it in a new process. It should also have a shell variable similar to PATH in bash. Shell variables are set as follows:
PATH=/usr/bin:/bin
The executable for the command is searched in the directories in the path and the first one found should be executed.
mosh should also be able to handle pipes (not more than one pipe) similar to bash.
Implementation in C
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#define INPUT_SIZE 512
#define BUF_SIZE 10
char** split_String(char *input_ptr,char *buffer[BUF_SIZE],int *n_args);
/**
*Main function of the shell
*/
int main(){
char input[INPUT_SIZE];
char *buffer[BUF_SIZE];
char *pipe_forw[BUF_SIZE];
char *ext_array[BUF_SIZE];
char **buf;
char *input_ptr;
int status_1,status_2;
int counter=0;int ispipe;
int pfds[2];
int num_of_args=0;int prev_args_pipe=0;
int n_args;
printf("\n\t----------------------------------------------------");
printf("\n\t\t\tWelcome to MY SHELL");
printf("\n\t----------------------------------------------------\n\n");
while(1){
//Get the directory root path
char root[100];
printf("mosh:~");
printf("%s%s",getcwd(root,100),"$ ");
/*char *PATH;
PATH="/bin/";
char prog[INPUT_SIZE];
strcpy(prog, PATH);*/
//Take the std input from the keyboard
fgets(input,sizeof(input),stdin);
input_ptr=input;
//Split the input string
buf=split_String(input_ptr,buffer,&n_args);
//Check whether # of arguments is zero
if(n_args==0){
continue;
}
ispipe=0;
//Take the split result to a char * array
for(counter=0;counter<sizeof(buf);counter++){
if((&*buf[counter])=='\0')
break;
num_of_args=counter+1;
//Take and hold the pipe index from the char * array
if(strcmp(&*buf[counter],"|")==0){
ispipe=num_of_args;
}
if(&*buf[counter]=='\0'){
ext_array[counter]='\0';
break;
}
else
ext_array[counter]=&*buf[counter];
}
//Compare the input string is exit
if(strcasecmp(&*buf[0],"exit")==0){
exit(0);
}
//Check the cd command
if(strcasecmp(&*buf[0],"cd")==0){
chdir(ext_array[1]);
continue;
}
//Check the path
if(strcasecmp(&*buf[0],"$path")==0){
printf("%s\n",getenv("PATH"));
//printf("%s\n",PATH);
continue;
}
//Create a new process
pid_t pid=fork();
pid_t pid_2;
if(pid == -1){
perror("Undefined");
continue;
}
//Child running
else if(pid==0){
//Check whether input includes the pipe
if(ispipe){
//Count the # of args after the pipe symbol
prev_args_pipe=num_of_args-ispipe;
//These args put in to the another array
for(counter=0;counter<prev_args_pipe;counter++){
pipe_forw[counter]=ext_array[ispipe+counter];
pipe_forw[counter+1]='\0';
}
num_of_args=ispipe;
//Pipe symbol index convert to the NULL
ext_array[ispipe-1]='\0';
//Create the pipe
pipe(pfds);
//Run the child process
if((pid_2=fork())==0){
close(1);
dup(pfds[1]);
close(pfds[0]);
int chk_value=execvp(ext_array[0],ext_array);
if(chk_value == -1){
printf("Error: Command Not Found\n");
}
/*strcat(prog, ext_array[0]);
execv(prog,ext_array);*/
exit(127);
}
//Run the parent process
else{
waitpid(&status_2);
close(0);
dup(pfds[0]);
close(pfds[1]);
int chk_value=execvp(pipe_forw[0],pipe_forw);
if(chk_value == -1){
printf("Error: Command Not Found\n");
}
/*strcat(prog, pipe_forw[0]);
execv(prog,pipe_forw);*/
exit(128);
}
}
//Run the command without pipe
else{
int chk_value=execvp(buffer[0],buffer);
if(chk_value == -1){
printf("Error: Command Not Found\n");
}
/*strcat(prog, buffer[0]);
execv(prog,buffer);*/
}
exit(127);
}
//Parent is waiting until child terminates
else{
wait(&status_1);
}
}
return 0;
}
/**
*Split the input buffer string
*/
char** split_String(char *input_ptr,char *buffer[BUF_SIZE],int *n_args){
int counter;
for(counter=0;counter<BUF_SIZE;counter++){
if((buffer[counter]=strtok(input_ptr," \t\n"))=='\0'){
*n_args=counter;
break;
}
input_ptr=NULL;
}
return buffer;
}
PATH=/usr/bin:/bin
The executable for the command is searched in the directories in the path and the first one found should be executed.
mosh should also be able to handle pipes (not more than one pipe) similar to bash.
Implementation in C
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#define INPUT_SIZE 512
#define BUF_SIZE 10
char** split_String(char *input_ptr,char *buffer[BUF_SIZE],int *n_args);
/**
*Main function of the shell
*/
int main(){
char input[INPUT_SIZE];
char *buffer[BUF_SIZE];
char *pipe_forw[BUF_SIZE];
char *ext_array[BUF_SIZE];
char **buf;
char *input_ptr;
int status_1,status_2;
int counter=0;int ispipe;
int pfds[2];
int num_of_args=0;int prev_args_pipe=0;
int n_args;
printf("\n\t----------------------------------------------------");
printf("\n\t\t\tWelcome to MY SHELL");
printf("\n\t----------------------------------------------------\n\n");
while(1){
//Get the directory root path
char root[100];
printf("mosh:~");
printf("%s%s",getcwd(root,100),"$ ");
/*char *PATH;
PATH="/bin/";
char prog[INPUT_SIZE];
strcpy(prog, PATH);*/
//Take the std input from the keyboard
fgets(input,sizeof(input),stdin);
input_ptr=input;
//Split the input string
buf=split_String(input_ptr,buffer,&n_args);
//Check whether # of arguments is zero
if(n_args==0){
continue;
}
ispipe=0;
//Take the split result to a char * array
for(counter=0;counter<sizeof(buf);counter++){
if((&*buf[counter])=='\0')
break;
num_of_args=counter+1;
//Take and hold the pipe index from the char * array
if(strcmp(&*buf[counter],"|")==0){
ispipe=num_of_args;
}
if(&*buf[counter]=='\0'){
ext_array[counter]='\0';
break;
}
else
ext_array[counter]=&*buf[counter];
}
//Compare the input string is exit
if(strcasecmp(&*buf[0],"exit")==0){
exit(0);
}
//Check the cd command
if(strcasecmp(&*buf[0],"cd")==0){
chdir(ext_array[1]);
continue;
}
//Check the path
if(strcasecmp(&*buf[0],"$path")==0){
printf("%s\n",getenv("PATH"));
//printf("%s\n",PATH);
continue;
}
//Create a new process
pid_t pid=fork();
pid_t pid_2;
if(pid == -1){
perror("Undefined");
continue;
}
//Child running
else if(pid==0){
//Check whether input includes the pipe
if(ispipe){
//Count the # of args after the pipe symbol
prev_args_pipe=num_of_args-ispipe;
//These args put in to the another array
for(counter=0;counter<prev_args_pipe;counter++){
pipe_forw[counter]=ext_array[ispipe+counter];
pipe_forw[counter+1]='\0';
}
num_of_args=ispipe;
//Pipe symbol index convert to the NULL
ext_array[ispipe-1]='\0';
//Create the pipe
pipe(pfds);
//Run the child process
if((pid_2=fork())==0){
close(1);
dup(pfds[1]);
close(pfds[0]);
int chk_value=execvp(ext_array[0],ext_array);
if(chk_value == -1){
printf("Error: Command Not Found\n");
}
/*strcat(prog, ext_array[0]);
execv(prog,ext_array);*/
exit(127);
}
//Run the parent process
else{
waitpid(&status_2);
close(0);
dup(pfds[0]);
close(pfds[1]);
int chk_value=execvp(pipe_forw[0],pipe_forw);
if(chk_value == -1){
printf("Error: Command Not Found\n");
}
/*strcat(prog, pipe_forw[0]);
execv(prog,pipe_forw);*/
exit(128);
}
}
//Run the command without pipe
else{
int chk_value=execvp(buffer[0],buffer);
if(chk_value == -1){
printf("Error: Command Not Found\n");
}
/*strcat(prog, buffer[0]);
execv(prog,buffer);*/
}
exit(127);
}
//Parent is waiting until child terminates
else{
wait(&status_1);
}
}
return 0;
}
/**
*Split the input buffer string
*/
char** split_String(char *input_ptr,char *buffer[BUF_SIZE],int *n_args){
int counter;
for(counter=0;counter<BUF_SIZE;counter++){
if((buffer[counter]=strtok(input_ptr," \t\n"))=='\0'){
*n_args=counter;
break;
}
input_ptr=NULL;
}
return buffer;
}
Comments
Post a Comment