像普通C程序一样编译运行即可。
mini.h
mini.c
mini.h
/*
filename:mini.h
*/
#define WHITESPACE " ., &"
#define MAX_ARG_LEN 10
#define MAX_DIRS 20
#define MAX_PATH_LEN 100
#define STD_INPUT 0
#define STD_OUTPUT 1
#define MAX_ARGS 5
struct command_t {
int argc;
char * name;
char * argv[MAX_ARGS];
};
#define WHITESPACE " ., &"
#define MAX_ARG_LEN 10
#define MAX_DIRS 20
#define MAX_PATH_LEN 100
#define STD_INPUT 0
#define STD_OUTPUT 1
#define MAX_ARGS 5
struct command_t {
int argc;
char * name;
char * argv[MAX_ARGS];
};
mini.c
/*
***********************************************************
*MiniShell
*filename:mini.c
*it's a simple shell written by Manio(maniosterATgmail.com)
*Bugs:1.the commands must be seprated by only one whitespace
*and more and more bugs here...
*the part of pipe havn't be written.
*date,addr:08/16/2006 Yangshuo,China
*********************************************************** */
#include < fcntl.h >
#include < stdio.h >
#include < sys / types.h >
#include < sys / wait.h >
#include < string .h >
#include < unistd.h >
#include " mini.h "
// #define DEBUG 1
void printLineHead();
void parseCommand( char * , char ** );
char * GetChkFullPath( char ** , char ** );
main(){
int i,j; /* for common use */
int stat; /* used by wait() */
int isInRedir,isOutRedir,isPipe;
int fid; /* for file opening */
char orginalCmd[ 100 ]; /* store the command user typed */
char * dir[MAX_DIRS];
struct command_t command;
char * tempstr[ 7 ];
/* initial argv
*maybe a error will be occured if argv is not be initialed
*/
for ( i = 0 ; i < MAX_ARGS ; i ++ )
command.argv[i] = ( char * )malloc(MAX_ARG_LEN);
while ( 1 ){
printLineHead();
gets(orginalCmd); /* read user's input */
#ifdef DEBUG
printf( " ::::after gets(orginalCmd):::: " );
printf( " orginalCmd=%s " ,orginalCmd);
printf( " :::::::::::::::::::::::::::::: " );
#endif
/* if "exit" inputed,exit the shell */
if (strcmp(orginalCmd, " exit " ) == 0 )
break ;
/* devide command line to several parts */
parseCommand(orginalCmd,command.argv);
/* get the amount of argv */
for (i = 0 ;command.argv[i] != NULL;i ++ );
command.argc = i;
#ifdef DEBUG
printf( " command.argc=%d " ,command.argc);
#endif
#ifdef DEBUG
printf( " ::::parseCommand command.argv:::: " );
printf( " command.name = %s " ,command.name);
int commandi;
for (commandi = 0 ;command.argv[commandi] != NULL;commandi ++ )
printf( " command.argv[%d]=%s " ,commandi,command.argv[commandi]);
printf( " ::::END command.argv:::: " );
#endif
/* get the dirs from PATH;PATH is a enviroment var */
#ifdef DEBUG
printf( " getDir start=========================== " );
#endif
getDir(dir);
#ifdef DEBUG
int diri = 0 ;
for (;dir[diri] != NULL;diri ++ )
{
printf( " in main dir[%d] is %s " ,diri,dir[diri]);
}
#endif
/* get the name of command,this must get the full path of the file,but here is for debug */
command.name = GetChkFullPath(command.argv,dir);
#ifdef DEBUG
printf( " in main after GetChkFullPath command.name=%s " ,command.name);
#endif
if (command.name == NULL ){
/* the command inputed is not valid or is empty */
continue ;
fprintf(stderr, " Command %s not found " , command.argv[ 0 ]);
}
/* scan < > | ,isPipe isInRedir and isOutRedir store the position of "< > |" */
isPipe = isInRedir = isOutRedir = 0 ;
for ( i = 0 ; command.argv[i] != NULL ; i ++ )
{
if ( strcmp( command.argv[i] , " < " ) == 0 ){
isInRedir = i;
}
if ( strcmp( command.argv[i] , " > " ) == 0 ){
isOutRedir = i;
}
if ( strcmp( command.argv[i] , " | " ) == 0 ){
isPipe = i;
}
}
#ifdef DEBUG
printf( " isin,inout,ispipe:%d%d%d " ,isInRedir,isOutRedir,isPipe);
#endif
#ifdef DEBUG
command.argv[ 3 ] = NULL;
printf( " show the argvs which is not set " );
for (i = 0 ; i < MAX_ARGS ; i ++ )
printf( " argv[%d]=%s " ,i,command.argv[i]);
#endif
/* excute a commmand */
if (fork() == 0 ){
#ifdef DEBUG
printf( " ::::::::::::::::In fork==0:::::::::::::::::: " );
#endif
if (isInRedir){
fid = open(command.argv[isInRedir + 1 ],O_RDONLY);
close(STD_INPUT); // close standard input
dup(fid); // redirect fid to standard input
close(fid);
command.argv[isInRedir] = NULL; /* ignore the word after isInRedir */
#ifdef DEBUG
printf( " ::::parseCommand command.argv:::: " );
printf( " command.name = %s " ,command.name);
for (commandi = 0 ;command.argv[commandi] != NULL;commandi ++ )
printf( " command.argv[%d]=%s " ,commandi,command.argv[commandi]);
printf( " ::::END command.argv:::: " );
#endif
}
if (isOutRedir){
fid = open(command.argv[isOutRedir + 1 ],O_WRONLY | O_CREAT);
close(STD_OUTPUT);
dup(fid);
close(fid);
command.argv[isOutRedir] = NULL;
#ifdef DEBUG
printf( " ::::parseCommand command.argv:::: " );
printf( " command.name = %s " ,command.name);
for (commandi = 0 ;command.argv[commandi] != NULL;commandi ++ )
printf( " command.argv[%d]=%s " ,commandi,command.argv[commandi]);
printf( " ::::END command.argv:::: " );
#endif
}
execv(command.name,command.argv); /* excute the command */
#ifdef DEBUG
printf( " ::::::::::::::::In fork==0 END:::::::::::::::::: " );
#endif
} else {
#ifdef DEBUG
printf( " ::::::::::::::::In fork!=0:::::::::::::::::: " );
#endif
wait( & stat); /* wait for the end of child process */
#ifdef DEBUG
printf( " ::::::::child process done!::IN FORK!=0:END::::: " );
#endif
}
// loopcount = 0;
} /* while */
#ifdef DEBUG
printf( " Shell terminaled " );
#endif
}
void printLineHead()
{
printf( " MANIO's miniSHELL> " );
}
/* *************************************************************
parseCommand()
*seprate cLine by WHITESPACE,put them to pchar[]
*#define WHITESPACE " ., &"
*bugs:This code does not handle multiple WHITESPACE characters
***************************************************************
*/
void parseCommand( char * cLine, char * pchar[]) {
int argc;
char * tCLine;
char ** clPtr;
// Initialization
tCLine = cLine;
clPtr = & tCLine;
argc = 0 ;
// This code does not handle multiple WHITESPACE characters
while ((pchar[argc ++ ] = strsep(clPtr, WHITESPACE)) != NULL);
pchar[argc -- ] = NULL; // Null terminated list of strings
}
/* ***************************************************************
*get the path in PATH seprated by ":"
*****************************************************************
*/
int getDir( char * dir[])
{
int i;
char * s;
char * oldpath;
char * ppath;
s = ( char * )getenv( " PATH " );
#ifdef DEBUG
printf( " s is %s " ,s);
printf( " s2=====%c " ,s[ 2 ]);
#endif
oldpath = ( char * )malloc(strlen(s) + 1 );
strcpy(oldpath,s);
#ifdef DEBUG
printf( " oldpath is %s " ,oldpath);
#endif
ppath = oldpath;
#ifdef DEBUG
printf( " ppath char is %c " , * ppath);
#endif
for (i = 0 ; * ppath != ' ' ;ppath ++ )
{
#ifdef DEBUG
printf( " in for ppath char is %c " , * ppath);
#endif
if ( * ppath == ' : ' )
{
dir[i ++ ] = oldpath;
* ppath = ' ' ;
oldpath = ppath + 1 ;
}
}
dir[i] = NULL;
#ifdef DEBUG
int diri = 0 ;
for (;dir[diri] != NULL;diri ++ )
{
printf( " dir[%d] is %s " ,diri,dir[diri]);
}
#endif
return 1 ;
}
/* ***************************************************************
*get and check the full path which the user inputed
*dir :dirs in PATH
*argv:argv in command_t
*****************************************************************
*/
char * GetChkFullPath( char ** argv, char ** dir)
{
#ifdef DEBUG
printf( " :::::::::::GetChkFullPath start " );
printf( " argv[0]=%s dir[0]=%s " ,argv[ 0 ],dir[ 0 ]);
#endif
char fullpath[MAX_PATH_LEN];
char * result;
int i;
result = NULL;
if ( * argv[ 0 ] != ' / ' )
{
// *argv[0] != ''
#ifdef DEBUG
printf( " JUGE argv[0]!=/ " );
#endif
for (i = 0 ;dir[i] != NULL ;i ++ )
{
strcpy(fullpath,dir[i]);
strcat(fullpath, " / " );
strcat(fullpath,argv[ 0 ]);
#ifdef DEBUG
printf( " after strcat fullpath:%s " ,fullpath);
#endif
if (access(fullpath, X_OK | F_OK) != - 1 ){
#ifdef DEBUG
printf( " FOUND %s in %s " ,argv[ 0 ],dir[i]);
#endif
result = ( char * )malloc(strlen(fullpath) + 1 );
strcpy(result,fullpath);
break ;
}
}
} else {
#ifdef DEBUG
printf( " JUGE argv[0]==/ " );
#endif
if (access(argv[ 0 ], X_OK | F_OK) != - 1 ){
#ifdef DEBUG
printf( " FOUND %s " ,argv[ 0 ]);
#endif
result = ( char * )malloc(strlen(argv[ 0 ]) + 1 );
strcpy(result , argv[ 0 ]);
}
}
if (result == NULL ){
printf( " %s is not a command. " ,argv[ 0 ]);
return NULL;
} else {
#ifdef DEBUG
printf( " GetChkFullPath end result == %s " ,result);
#endif
return result;
}
}
*MiniShell
*filename:mini.c
*it's a simple shell written by Manio(maniosterATgmail.com)
*Bugs:1.the commands must be seprated by only one whitespace
*and more and more bugs here...
*the part of pipe havn't be written.
*date,addr:08/16/2006 Yangshuo,China
*********************************************************** */
#include < fcntl.h >
#include < stdio.h >
#include < sys / types.h >
#include < sys / wait.h >
#include < string .h >
#include < unistd.h >
#include " mini.h "
// #define DEBUG 1
void printLineHead();
void parseCommand( char * , char ** );
char * GetChkFullPath( char ** , char ** );
main(){
int i,j; /* for common use */
int stat; /* used by wait() */
int isInRedir,isOutRedir,isPipe;
int fid; /* for file opening */
char orginalCmd[ 100 ]; /* store the command user typed */
char * dir[MAX_DIRS];
struct command_t command;
char * tempstr[ 7 ];
/* initial argv
*maybe a error will be occured if argv is not be initialed
*/
for ( i = 0 ; i < MAX_ARGS ; i ++ )
command.argv[i] = ( char * )malloc(MAX_ARG_LEN);
while ( 1 ){
printLineHead();
gets(orginalCmd); /* read user's input */
#ifdef DEBUG
printf( " ::::after gets(orginalCmd):::: " );
printf( " orginalCmd=%s " ,orginalCmd);
printf( " :::::::::::::::::::::::::::::: " );
#endif
/* if "exit" inputed,exit the shell */
if (strcmp(orginalCmd, " exit " ) == 0 )
break ;
/* devide command line to several parts */
parseCommand(orginalCmd,command.argv);
/* get the amount of argv */
for (i = 0 ;command.argv[i] != NULL;i ++ );
command.argc = i;
#ifdef DEBUG
printf( " command.argc=%d " ,command.argc);
#endif
#ifdef DEBUG
printf( " ::::parseCommand command.argv:::: " );
printf( " command.name = %s " ,command.name);
int commandi;
for (commandi = 0 ;command.argv[commandi] != NULL;commandi ++ )
printf( " command.argv[%d]=%s " ,commandi,command.argv[commandi]);
printf( " ::::END command.argv:::: " );
#endif
/* get the dirs from PATH;PATH is a enviroment var */
#ifdef DEBUG
printf( " getDir start=========================== " );
#endif
getDir(dir);
#ifdef DEBUG
int diri = 0 ;
for (;dir[diri] != NULL;diri ++ )
{
printf( " in main dir[%d] is %s " ,diri,dir[diri]);
}
#endif
/* get the name of command,this must get the full path of the file,but here is for debug */
command.name = GetChkFullPath(command.argv,dir);
#ifdef DEBUG
printf( " in main after GetChkFullPath command.name=%s " ,command.name);
#endif
if (command.name == NULL ){
/* the command inputed is not valid or is empty */
continue ;
fprintf(stderr, " Command %s not found " , command.argv[ 0 ]);
}
/* scan < > | ,isPipe isInRedir and isOutRedir store the position of "< > |" */
isPipe = isInRedir = isOutRedir = 0 ;
for ( i = 0 ; command.argv[i] != NULL ; i ++ )
{
if ( strcmp( command.argv[i] , " < " ) == 0 ){
isInRedir = i;
}
if ( strcmp( command.argv[i] , " > " ) == 0 ){
isOutRedir = i;
}
if ( strcmp( command.argv[i] , " | " ) == 0 ){
isPipe = i;
}
}
#ifdef DEBUG
printf( " isin,inout,ispipe:%d%d%d " ,isInRedir,isOutRedir,isPipe);
#endif
#ifdef DEBUG
command.argv[ 3 ] = NULL;
printf( " show the argvs which is not set " );
for (i = 0 ; i < MAX_ARGS ; i ++ )
printf( " argv[%d]=%s " ,i,command.argv[i]);
#endif
/* excute a commmand */
if (fork() == 0 ){
#ifdef DEBUG
printf( " ::::::::::::::::In fork==0:::::::::::::::::: " );
#endif
if (isInRedir){
fid = open(command.argv[isInRedir + 1 ],O_RDONLY);
close(STD_INPUT); // close standard input
dup(fid); // redirect fid to standard input
close(fid);
command.argv[isInRedir] = NULL; /* ignore the word after isInRedir */
#ifdef DEBUG
printf( " ::::parseCommand command.argv:::: " );
printf( " command.name = %s " ,command.name);
for (commandi = 0 ;command.argv[commandi] != NULL;commandi ++ )
printf( " command.argv[%d]=%s " ,commandi,command.argv[commandi]);
printf( " ::::END command.argv:::: " );
#endif
}
if (isOutRedir){
fid = open(command.argv[isOutRedir + 1 ],O_WRONLY | O_CREAT);
close(STD_OUTPUT);
dup(fid);
close(fid);
command.argv[isOutRedir] = NULL;
#ifdef DEBUG
printf( " ::::parseCommand command.argv:::: " );
printf( " command.name = %s " ,command.name);
for (commandi = 0 ;command.argv[commandi] != NULL;commandi ++ )
printf( " command.argv[%d]=%s " ,commandi,command.argv[commandi]);
printf( " ::::END command.argv:::: " );
#endif
}
execv(command.name,command.argv); /* excute the command */
#ifdef DEBUG
printf( " ::::::::::::::::In fork==0 END:::::::::::::::::: " );
#endif
} else {
#ifdef DEBUG
printf( " ::::::::::::::::In fork!=0:::::::::::::::::: " );
#endif
wait( & stat); /* wait for the end of child process */
#ifdef DEBUG
printf( " ::::::::child process done!::IN FORK!=0:END::::: " );
#endif
}
// loopcount = 0;
} /* while */
#ifdef DEBUG
printf( " Shell terminaled " );
#endif
}
void printLineHead()
{
printf( " MANIO's miniSHELL> " );
}
/* *************************************************************
parseCommand()
*seprate cLine by WHITESPACE,put them to pchar[]
*#define WHITESPACE " ., &"
*bugs:This code does not handle multiple WHITESPACE characters
***************************************************************
*/
void parseCommand( char * cLine, char * pchar[]) {
int argc;
char * tCLine;
char ** clPtr;
// Initialization
tCLine = cLine;
clPtr = & tCLine;
argc = 0 ;
// This code does not handle multiple WHITESPACE characters
while ((pchar[argc ++ ] = strsep(clPtr, WHITESPACE)) != NULL);
pchar[argc -- ] = NULL; // Null terminated list of strings
}
/* ***************************************************************
*get the path in PATH seprated by ":"
*****************************************************************
*/
int getDir( char * dir[])
{
int i;
char * s;
char * oldpath;
char * ppath;
s = ( char * )getenv( " PATH " );
#ifdef DEBUG
printf( " s is %s " ,s);
printf( " s2=====%c " ,s[ 2 ]);
#endif
oldpath = ( char * )malloc(strlen(s) + 1 );
strcpy(oldpath,s);
#ifdef DEBUG
printf( " oldpath is %s " ,oldpath);
#endif
ppath = oldpath;
#ifdef DEBUG
printf( " ppath char is %c " , * ppath);
#endif
for (i = 0 ; * ppath != ' ' ;ppath ++ )
{
#ifdef DEBUG
printf( " in for ppath char is %c " , * ppath);
#endif
if ( * ppath == ' : ' )
{
dir[i ++ ] = oldpath;
* ppath = ' ' ;
oldpath = ppath + 1 ;
}
}
dir[i] = NULL;
#ifdef DEBUG
int diri = 0 ;
for (;dir[diri] != NULL;diri ++ )
{
printf( " dir[%d] is %s " ,diri,dir[diri]);
}
#endif
return 1 ;
}
/* ***************************************************************
*get and check the full path which the user inputed
*dir :dirs in PATH
*argv:argv in command_t
*****************************************************************
*/
char * GetChkFullPath( char ** argv, char ** dir)
{
#ifdef DEBUG
printf( " :::::::::::GetChkFullPath start " );
printf( " argv[0]=%s dir[0]=%s " ,argv[ 0 ],dir[ 0 ]);
#endif
char fullpath[MAX_PATH_LEN];
char * result;
int i;
result = NULL;
if ( * argv[ 0 ] != ' / ' )
{
// *argv[0] != ''
#ifdef DEBUG
printf( " JUGE argv[0]!=/ " );
#endif
for (i = 0 ;dir[i] != NULL ;i ++ )
{
strcpy(fullpath,dir[i]);
strcat(fullpath, " / " );
strcat(fullpath,argv[ 0 ]);
#ifdef DEBUG
printf( " after strcat fullpath:%s " ,fullpath);
#endif
if (access(fullpath, X_OK | F_OK) != - 1 ){
#ifdef DEBUG
printf( " FOUND %s in %s " ,argv[ 0 ],dir[i]);
#endif
result = ( char * )malloc(strlen(fullpath) + 1 );
strcpy(result,fullpath);
break ;
}
}
} else {
#ifdef DEBUG
printf( " JUGE argv[0]==/ " );
#endif
if (access(argv[ 0 ], X_OK | F_OK) != - 1 ){
#ifdef DEBUG
printf( " FOUND %s " ,argv[ 0 ]);
#endif
result = ( char * )malloc(strlen(argv[ 0 ]) + 1 );
strcpy(result , argv[ 0 ]);
}
}
if (result == NULL ){
printf( " %s is not a command. " ,argv[ 0 ]);
return NULL;
} else {
#ifdef DEBUG
printf( " GetChkFullPath end result == %s " ,result);
#endif
return result;
}
}