自己写的SHELL。
以此程序了解一些SHELL的运行机制。
像一般C一样编译运行就可以了。
[code:1]/*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];
};[/code:1]
[code:1]/************************************************************
*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;
}
}
[/code:1]