1. 程式人生 > >利用linux下的c語言程式設計來簡單的實現一個shell功能實現!

利用linux下的c語言程式設計來簡單的實現一個shell功能實現!

學習了fork(),exec()函式之後,讓我們來簡單是實現來實現一個shell

裡面用到了一些函式,進行對字串進行做一下簡單的處理!

#include<stdio.h>
#include<errno.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<pwd.h>
#define NUM 1024
#define SIZE 50

int  mystrtok(char *argv[],char *string);

//這個函式做的是對字串的分割,把命令分割開,用到了字串的分割函式
int mystrtok(char *argv[],char *string)
{
 int i=0;
 char delim[]=" ";
 char *p;
 argv[0]=strtok(string,delim);//字串分割函式的使用
 //printf("%s\n",argv[0]);
 while(argv[i]!=NULL)
 {
  argv[++i]=strtok(NULL,delim);
  //printf("%s is %d\n",argv[i],i);
 }
return 0;
}

//獲得一個命令提示符的字串
char *getusername(char buffer[NUM])
{
 uid_t userid;
 char *username;
 char *hostname;
 char *ptr,*p;
 char buf1[1024],buf2[1024];
 char *delim=".";
 int id;
 getwd(buf2);//這段程式碼說明的是對命令提示的路徑獲得
 username=getenv("USER");//呼叫getenv函式,來獲得shell命令的提示中的使用者名稱
 strcpy(buffer,username);
 strcat(buffer,"@");
 id=gethostname(buf1,sizeof buf1);//呼叫此函式來獲取shell命令的提示中的主機名
 p=strtok(buf1,delim);//對主機進行擷取
 strcat(buffer,p);//字串的連線函式
 ptr=strrchr(buf2,'/');//字串的從後往前進行擷取的函式,講多得shell命令提示中的路徑
 //比較字串,判斷使用者的路徑是在"/","~",還是其他當中
 if(strcmp(ptr,"/")==0)
 {
  ptr="/";
 }
 else if(strcmp(ptr,"~")==0)
 {
  ptr="~";
 }
 else
 {
  ptr=strtok(ptr,"/");
  
 }

//把獲得的 [使用者名稱@主機名  路徑]連線在一起
 strcat(buffer," ");
 strcat(buffer,ptr);
return buffer;
}
int main()
{
 pid_t pid;
 int status;
 char *argv[NUM];
 char buffer[NUM];
 char str[NUM];
 int j=-1;
 char *string=NULL;
 string=getenv("USER");

//當前使用者是root使用者還是普通使用者,通過字串的比較,如果是root,則返回0;
 if((strcmp(string,"root"))==0)
 {
  j=0;
 }
 while(1){

//通過呼叫上面自定義的getusername()函式,來得到shell命令中的提示
  printf("[%s]",getusername(buffer));
  //判斷是使用root的提示#,還是其他使用者的$

if(j==0)
  {
   printf("# ");
  }
  else
  { 


    printf("$ ");
  }

//字串的輸入,要用gets函式或者用fgets函式,因為scanf函式把空格看成字串的結束
  gets(str);

//呼叫字串的分割函式,獲得要截取出來的命令和命令引數,例如:ls -a分別放到argv[0],argv[1]中
  status=mystrtok(argv,str);
  if(status!=0)
  {
   printf("fail to getargv!\n");
  }

//通過fork()函式來建立一個父程序和一個子程序
  pid=fork();
  if(-1==pid)
  {
   printf("your fork failed!\n");
  } 
  else if(pid==0)
  { 

//子程序用來對shell命令程序程序解釋執行的
   if(argv[1]!=NULL)
   {
    execvp(argv[0],argv);
   }
   else if(argv[1]==NULL)
   {
    execlp(argv[0],argv[0],NULL,NULL);
   }
  }
  else
  {

//父程序用來等待子程序的結束,然後再迴圈輸入shell命令
   if(wait(&status)==-1)
   {
    printf("wait failed!\n");
    exit(1);
   }
  
  }
 }
 return 0;
}

裡面用到了很多的系統函式的呼叫,沒有細細的解釋說明,留給大家自學啦,哈哈!!