0% found this document useful (0 votes)
169 views

Simple Shell

This C program implements a basic shell with commands like cd, ls, help, exit, and handles piping. It uses libraries like readline, history for input handling and dup, wait, fork, execvp for command execution. Custom commands like corona and haha are also implemented. The program tokenizes the input on spaces and pipes, determines the command type, and executes the commands or pipes them accordingly.

Uploaded by

Hasan Farooq
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
169 views

Simple Shell

This C program implements a basic shell with commands like cd, ls, help, exit, and handles piping. It uses libraries like readline, history for input handling and dup, wait, fork, execvp for command execution. Custom commands like corona and haha are also implemented. The program tokenizes the input on spaces and pipes, determines the command type, and executes the commands or pipes them accordingly.

Uploaded by

Hasan Farooq
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

//NOTE::

// I have also used one EXTRA Library "READLINE"


// If library is not in your system it needs to be included first
// and then should be passed as a Parameter when Compiling...
// example : gcc [filename].c -lreadline
// This library has builtin functions that handles the input taken when working
with SHELL
// some part of it is taken from online sites to make it look better and execute
more commands
// i.e. WELCOME, EXIT, CD, HELP, GREET, GOODBYE etc commands are there
// I have done pipes, dup and system calss stuff etc myself and in other functions
I have only Modified
// STDOUT_FILENO is the same as 1 passed in file descriptor and vice versa for
STDIN (read somewhere on net)

// You can also try CORONA, HAHA, HELP Commands :D

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<readline/readline.h>
#include<readline/history.h>

#define max_len 1000


#define max_commands 100

// Clearing the shell using escape sequences


#define clear() printf("\033[H\033[J")

void init_shell()
{
clear();
printf("\n\n\t-We're starting in 3 Seconds...-");
printf("\n\n\n\n*******************"
"***********************");
char* username = getenv("USER");
printf("\n\n\nhaha@%s", username);
printf("\n");
sleep(3);
clear();
}

int takeInput(char* str)


{
char* buf;

buf = readline("\n>> ");


if (strlen(buf) != 0)
{
add_history(buf);
strcpy(str, buf);
return 0;
}
return 1;
}
//current location
void printDir()
{
char cwd[1024];
getcwd(cwd, sizeof(cwd));
printf("\n We're here : %s", cwd);
}

// system commands
void execute_commands(char** command)
{
pid_t pid = fork();
if (pid == 0)
{
execvp(command[0], command);
exit(0);
}
else
{
wait(NULL);
return;
}
}

//piped commands
void execute_pipes(char** parsed, char** parsedpipe)
{
int fd[2];
pid_t p1, p2;

p1 = fork();
if (p1 == 0)
{
close(fd[0]);
dup2(fd[1], STDOUT_FILENO);
close(fd[1]);
execvp(parsed[0], parsed);
}
else
{
p2 = fork();
if (p2 == 0)
{
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
execvp(parsedpipe[0], parsedpipe);
}
else
{
wait(NULL);
wait(NULL);
}
}
}

void help()
{
puts("\n***WELCOME !!! Here's shell HELP... ***"
"\n\n-Use the shell at your own risk... :D"
"\n Commands included : "
"\n> cd"
"\n> ls"
"\n> help"
"\n> exit"
"\n> corona"
"\n> haha"
"\n> other basic commands available in Ubuntu Terminal"
"\n> pipe handling"
"\n> Help will go away in 15 seconds...");
return;
}

//new commands...
int execute_extra_commands(char** parsed)
{
int NoOfOwnCmds = 5, i, switchOwnArg = 0;
char* ListOfOwnCmds[NoOfOwnCmds];
char* username;

ListOfOwnCmds[0] = "exit";
ListOfOwnCmds[1] = "cd";
ListOfOwnCmds[2] = "help";
ListOfOwnCmds[3] = "haha";
ListOfOwnCmds[4] = "corona";

for (i = 0; i < NoOfOwnCmds; i++) {


if (strcmp(parsed[0], ListOfOwnCmds[i]) == 0) {
switchOwnArg = i + 1;
break;
}
}

switch (switchOwnArg) {
case 1:
printf("\nGoodbye\n");
exit(0);
case 2:
chdir(parsed[1]);
return 1;
case 3:
help();
return 1;
case 4:
username = getenv("USER");
printf("\nHello %s.\nMind that this is "
"not a place to play around."
"\nUse help to know more..\n",
username);
return 1;
case 5:
printf("\nHello.. I hope you're fine and Safe."
"\nYou shouldn't execute such commands. "
"\nBTW please stay home and isolated"
"\n And enjoy healthy Holidays....\n");
return 1;
default:
break;
}

return 0;
}

//reads pipe command...


int read_pipe(char* line, char** strpiped)
{
for (int i = 0; i < 2; i++)
{
strpiped[i] = strsep(&line, "|"); //token wise separates... on "|"
if (strpiped[i] == NULL) //if null
break;
}
if (strpiped[1] == NULL)
return 0; //if no pipe is found.
return 1;
}

//separates space-wise
void read_space(char* line, char** parsed)
{
for (int i = 0; i < max_commands; i++)
{
parsed[i] = strsep(&line, " "); //token-wise separation on " "
if (parsed[i] == NULL) //if no space is there
break;
if (strlen(parsed[i]) == 0)
i--;
}
}

//finds out what type of command it is.. pipe ? own ? built-in ? space ?
int which_type(char* line, char** parsed, char** parsedpipe)
{
char* strpiped[2];
int piped = 0;

piped = read_pipe(line, strpiped); //return 1 when piped == done...

if (piped)
{
read_space(strpiped[0], parsed);
read_space(strpiped[1], parsedpipe);
}
else
read_space(line, parsed);

if (execute_extra_commands(parsed))
return 0;
else
return 1 + piped; //if piped than greater than 1 else 1
}

int main()
{
char input[max_len], *commands[max_commands];
char* commandsPiped[max_commands];
int execFlag = 0;
help();
sleep(15);
clear();
init_shell();

while (1) {
printDir();
if (takeInput(input)) //takes input using readline library
continue;
execFlag = which_type(input,commands,commandsPiped); //flag to know
command-type
if (execFlag == 1)
execute_commands(commands);
if (execFlag == 2)
execute_pipes(commands, commandsPiped);
}
return 0;
}

You might also like