【Linux】手搓shell

手搓shell

代码

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


#define ZERO '\0'
#define SIZE 512
#define SEP " "
#define NUM 32
#define Skiopath(p) do{ p += strlen(p-1);while(*p!='/')p--;}while(0)



char *gArgv[NUM];
char cwd[SIZE*2];
int lastcode =0;

void Die()
{
    exit(1);
}
const char *Gethome()
{
    const char *home =getenv("HOME");
    if(home==NULL)return "/";
    return home;
}
const char *GetuserName()
{
    const char *name= getenv("USER");
    if(name==NULL)return "None";
    return name;
}
const char *GethostName()
{
    const char *hostname = getenv("HOSTNAME");
    if(hostname==NULL)return "None";
    return hostname;
}
const char *GetCwd()
{
    const char *cwd=getenv("PWD");
    if(cwd==NULL)return "None";
    return cwd;
}
void Makecommandline_print()
{
    char line[SIZE];
    const char *username = GetuserName();
    const char *hostname = GethostName();
    const char *cwd = GetCwd();
    Skiopath(cwd);
    snprintf(line,SIZE,"[%s@%s %s]> ",username,hostname,strlen(cwd)==1?"/":cwd+1);
    printf("%s",line);
    fflush(stdout);
}
int Getusercommand(char command[],size_t n)
{
    char *s = fgets(command,n,stdin);
    if(s==NULL)return 1;
    command[strlen(command)-1]=ZERO;
    return strlen(command);
}

void Splitcommand(char command[],size_t n)
{
    //"ls -a -l -n"-> "ls" "-a" "-l" "-n"
    gArgv[0] = strtok(command,SEP);
    int index =1;
    while((gArgv[index++]=strtok(NULL,SEP)));//done,故意写成=,表示先赋值,在判断。分割之后,strtok会返回NULL,刚好让gArgv最后一个元素是NULL,并且while判断结束

}

void Executecommand()
{

    pid_t id =fork();
    if(id<0) Die();
    else if(id==0)
    {
        //child
        execvp(gArgv[0],gArgv);
        exit(errno);
    }
    else{
        //father
        int status =0;
        pid_t rid = waitpid(id,&status,0);
        if(rid>0)
        {
            lastcode = WEXITSTATUS(status);
            if(lastcode!=0)printf("%s:%s:%d\n",gArgv[0],strerror(lastcode),lastcode);
            
        }
    }

}
void Cd()
{
    const char *path = gArgv[1];
    if(path==NULL)path=Gethome();
    //path 一定存在
    chdir(path);
    //刷新环境变量
    char temp[SIZE*2];
    getcwd(temp,sizeof(temp));
    //导环境变量
    snprintf(cwd,sizeof(cwd),"PWD=%s",temp);
    putenv(cwd);
}
int Checkbuilding()
{
    int yes =0;
    const char *enter_cmd = gArgv[0];
    if(strcmp(enter_cmd,"cd")==0)
    {
    
        yes =1;
        Cd();
    }
    else if(strcmp(enter_cmd,"echo")==0&&strcmp(gArgv[1],"$?")==0)
    {
        yes=1;
        printf("%d\n",lastcode);
        lastcode=0;
    }
    return yes;
}
int main()
{
    int quit =0 ;
    while(!quit)
    {
        //1.输出一个命令行
        Makecommandline_print();
        
        //2.获取用户命令字符串
        char usercommand[SIZE];
        int n = Getusercommand(usercommand,sizeof(usercommand));
        
        //3.命令行字符串分割
        Splitcommand(usercommand,sizeof(usercommand));
        
        //4.检查命令是否是内建命令
        n=Checkbuilding();
        if(n)continue;
        //n.执行命令
        Executecommand();

    }
    return 0;
}
相关推荐
deng-c-f几秒前
Linux C/C++ 学习日记(22):Reactor模式(二):实现简易的webserver(响应http请求)
linux·c语言·网络编程·reactor·http_server
BTU_YC6 分钟前
CentOS 7 虚拟IP配置指南:使用传统network-scripts实现高可用
linux·tcp/ip·centos
陌路207 分钟前
LINUX14 进程间的通信 - 管道
linux·网络
W_chuanqi10 分钟前
RDEx:一种效果驱动的混合单目标优化器,自适应选择与融合多种算子与策略
人工智能·算法·机器学习·性能优化
大聪明-PLUS16 分钟前
从头开始为 ARM 创建 Ubuntu 映像
linux·嵌入式·arm·smarc
L_090725 分钟前
【Algorithm】二分查找算法
c++·算法·leetcode
靠近彗星27 分钟前
3.3栈与队列的应用
数据结构·算法
chenzhou__29 分钟前
MYSQL学习笔记(个人)(第十五天)
linux·数据库·笔记·学习·mysql
序属秋秋秋1 小时前
《Linux系统编程之入门基础》【Linux基础 理论+命令】(上)
linux·运维·服务器·ubuntu·centos·命令模式
知白守黑2673 小时前
docker资源限制
运维·docker·容器