1. 程式人生 > >實現一個簡單的shell

實現一個簡單的shell

程式碼的詳細解釋都在裡面了~~~~

//自己實現一個簡單的shell
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
//1:獲取終端輸入(scanf接收一個輸入資訊)
//2:解析輸入(按空格解析到一個一個的命令引數)
//3:建立一個子程序:在子程序中級進行程式替換,讓子程序執行命令
//4:等待子程序執行完畢,收屍,獲取退出狀態碼

int argc;
char *argv[32];
int param_parse(char *buff)
{
    if(buff == NULL)
        return -1;
    char *ptr = buff;
    char *tmp = ptr;
    int argc = 0;
    while((*ptr) != '\0')
    {
        if(isspace(*ptr))//判斷是否為: 空格 /f   /n   /r  /t   /v
        {
        //如果返回值為真,且不是回車‘\0’(沒有結束)
        //將空格置為‘\0’
        //使用argv[argc]來儲存這個字串位置
        //迴圈,直到返回值為假或者結束
        //解決l     -s (多空格無法識別的問題)
            while(isspace(*ptr) && *ptr != '\0')
            {
                *ptr++ = '\0';
            }
            argv[argc++] = tmp;
            tmp = ptr;
        }
        ptr++;
   }
    argv[argc++] = tmp;
    argv[argc] = NULL;
    return 0;
}
int do_exec()
{
    int pid = 0;
    pid = fork();
    if(pid < 0)
    {
        perror("fork");
        return -1;
    }
    else if (pid == 0)
    {
        execvp(argv[0],argv);
        exit(0);
    }
    //父程序在這裡必須等待子程序退出,來觀察子程序為什麼會退出
    //是否出現了什麼錯誤,通過獲取狀態碼,並且轉換退出碼所對應
    //的錯誤資訊進行列印
    int statu;
    wait(&statu);
    //判斷子程序是否程式碼執行完畢退出
    if(WIFEXITED(statu))
    {
        //獲取到子程序的退出碼,轉換為文字資訊
        printf("%s",strerror(WEXITSTATUS(statu)));
    }
    return 0; 
}

int main()
{
    while(1)
    { 
        printf("shell> ");
        fflush(stdout);
        char buff[1024] = {0}; 
        if(scanf("%[^\n]%*c",buff) ==2) //scanf回車代表結束
        {
        getchar();//獲取一個回車,防止直接回車出現的死迴圈
        }
        //scanf本身遇見空格就要獲取一次,這樣就無法獲取完整命令
        //%[^\n]:獲取資料直到遇見\n為止
        //%*c    清空緩衝區,資料都不要(不然還存有是上一個\n)
        //從緩衝區取出,直接丟掉。防止回車死迴圈
        printf("%s\n",buff);
        param_parse(buff);
        do_exec();
    }
    return 0;
}