Tuesday, December 9, 2008

Interesting C Program -24

Hi all,
Here is the alpha version of the shell that I recently developed. This program runs fine in Linux. This shell will accept max 3 arguments.

Here's the program:

#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include "sys/wait.h"
char InputData[100];
char Command[100];
char Parameter1[100];
char Parameter2[100];
unsigned int CommandLength = 0;
unsigned int Parameter1Length = 0;
unsigned int Parameter2Length = 0;
unsigned int i=0;

void read_command(void);

int main()
{
int status;
printf("[Balaji]>");
while(1)
{
read_command();
if(fork()!=0)
{
//waitpid(-1,&status,0);
wait(&status);
}
else
{
if((Parameter1[0] == '\0')&&(Parameter2[0]=='\0'))
{
execlp(Command,Command,'\0');
}
else if((Parameter1[0] != '\0')&&(Parameter2[0]=='\0'))
{
execlp(Command,Command,Parameter1,'\0');
}
else
{
execlp(Command,Command,Parameter1,Parameter2,'\0');
}
}
printf("[Balaji]>");
for(i=0;i<CommandLength;i++)
{
Command[i] = '\0';
}
for(i=0;i<Parameter1Length;i++)
{
Parameter1[i] = '\0';
}
for(i=0;i {
Parameter2[i] = '\0';
}
}
}
void read_command(void)
{
unsigned char ParameterStart = 0;
gets(InputData);
for(i=0;InputData[i]!='\0';i++)
{
if((InputData[i]!=' ')&&(ParameterStart==0))
{
Command[i]=InputData[i];
CommandLength = i;
}
else if((InputData[i]==' ')&&(ParameterStart ==0))
{
Command[i]='\0';
CommandLength=i;
ParameterStart = 1;
}
else if((InputData[i]!=' ')&&(ParameterStart==1))
{
Parameter1[i-CommandLength-1] = InputData[i];
Parameter1Length = i-CommandLength-1;
}
else if((InputData[i]==' ')&&(ParameterStart==1))
{
Parameter1[i-CommandLength] = '\0';
Parameter1Length = (i-CommandLength);
ParameterStart = 2;
}
else if((InputData[i]!=' ')&&(ParameterStart==2))
{
Parameter2[i-CommandLength-Parameter1Length-1] = InputData[i];
Parameter2Length = i-CommandLength-Parameter1Length-1;
}
else if((InputData[i]==' ')&&(ParameterStart==1))
{
Parameter2[i-CommandLength-Parameter1Length] = '\0';
Parameter2Length = (i-CommandLength-Parameter1Length);
ParameterStart = 3;
}

}
if((InputData[i]=='\0')&&(ParameterStart==0))
{
Parameter1[0] = '\0';
Parameter2[0] = '\0';
Parameter1Length = 1;
Parameter2Length = 1;
}
}


.
gcc -o balaji shell.c
./balaji

3 comments:

Rohit N Elayath said...

Hi Balaji,
You could try this code. I haven't tested it as process invocation is different on Windows. This can accept upto 'n' params if your compiler supports an array overloading for execlp() as shown in this link: http://docs.sun.com/app/docs/doc/816-5167/execlp-2?a=view

Sadly this interface eats up all tabs. You'll have to reindent the code for better clarity.


#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include "sys/wait.h"

/*
* Keep a global variable for the length of the char array whose length was
* calculated most recently.
*/
int Length = 0;

/*
* Be careful when you use functional MACROs as they can screw your local
* scope if you have a variable with the same name as your control handle.
* Also, avoid these in multi-threaded programs.
*/
# define CALCHARARRAYLENGTH(arr) \
for(Length = 0; arr[Length] != 0; Length ++) ;

# define ArrayLength 0x7F
# define MaxParams 0x10

/* You could do this in a better fashion using pointers. It wouldn't
* hog so much memory.
*/
struct{
char Command[ArrayLength];
int NoOfStrings;
char Params[MaxParams][ArrayLength];
} CommandSplit;

int read_command(void);

void init_process(void);

void trim(char []);

void split_command(char []);

void execute();

int main()
{
char * prompt = "[Balaji]>";
while(1)
{
printf("\n%s", prompt);
if(!read_command())
{
continue;
}
execute();
}
}

void init_process(void)
{
int status;
if(fork()!=0)
{
//waitpid(-1,&status,0);
wait(&status);
}
}

int read_command(void)
{
char InputData[ArrayLength];
int InputDataLength;
gets(InputData);
trim(InputData);
CALCHARARRAYLENGTH(InputData);
InputDataLength = Length;
if(InputDataLength != 0)
{
split_command (InputData);
}
return InputDataLength;
}

/*
* Removes control characters from both ends of this string
*/
void trim (char String[])
{
int i = 0;
int j = 0;
CALCHARARRAYLENGTH(String);
int StringLength = Length;

/*
* Remove control characters from the begining of the string
*/
for(i = 0; i < StringLength; i ++)
{
if(String[i] > 0x20)
{
break;
}

for(j = i; j < StringLength; j ++)
{
String[j] = String[j + 1];
}
StringLength --;
}

/*
* Remove control characters from the end of the string
*/
for(i = StringLength - 1; i >= 0; i --)
{
if(String[i] > 0x20)
{
break;
}
StringLength --;
}
String[StringLength] = 0;
}

/*
* Splits this command using the structure defined above.
*/
void split_command(char Command[])
{
int i;
int j;
int NoOfParams = 0;
CommandSplit.Command[0] = 0;
while(1){
char TempString[ArrayLength];
trim(Command);
CALCHARARRAYLENGTH(Command);
int CommandLength = Length;

if(! CommandLength)
{
break;
}
for(i = 0; i < CommandLength; i ++)
{
TempString[i] = Command[i];
if(Command[i] <= 0x20)
{
break;
}
}
TempString[i] = 0;
CALCHARARRAYLENGTH(Command);
if(CommandSplit.Command[0] == 0)
{
for(i = 0; i <= Length; i ++)
{
CommandSplit.Command[i] = TempString [i];
}
}
else
{
for(i = 0; i <= Length; i ++)
{
CommandSplit.Params[NoOfParams][i] = TempString [i];
}
NoOfParams ++;
}
for(j = 0; j + i < CommandLength; j ++)
{
Command[j] = Command[i + j];
}
Command[j] = 0;
}
for(i = NoOfParams + 1; i < MaxParams; i ++)
{
CommandSplit.Params[i][0] = 0;
}

}

void execute()
{

init_process();

execlp(CommandSplit.Command,CommandSplit.Command,CommandSplit.Params);
}


Cheers!!!
Rohit

Rohit N Elayath said...

BTW, its just a modified version of your code.

Balaji V said...

Thanks for your comments Rohit.

Search Google

Books that I refer to...

  • The Complete Reference C, Fourth Edition
  • The C Programming Language