【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;
}
相关推荐
GeW8 小时前
新质生产力路线图Linux、数据库、国产化替代一次讲透
linux
zyl7659 小时前
FlashAttention 详解:从 GPU 硬件、普通 Attention 到分块计算与 Online Softmax
算法
aningx10 小时前
cachyos 从 GRUB 切换到 rEFInd
linux
第404号工位11 小时前
40块钱二手瘦客户端,如何跑满家庭物联网中枢?(拒绝Docker爆盘实录)
linux·架构·node.js
骑着蜗牛撵大象32713 小时前
Linux 进程间通信之管道:从 pipe() 的内核语义到 FIFO 落地排错
android·java·linux·系统编程·fifo·管道·进程间通信
爱读书的小胖13 小时前
LeetCode 122:买卖股票的最佳时机 II(C)解题分析
算法
结局无敌13 小时前
React Native for OpenHarmony 实战:三方库 react-native-modal-dialog 的鸿蒙化适配指南
深度学习·算法·react native·react.js·harmonyos
众壹新能源科技13 小时前
逆变器自带无功不够用,加装5MVar SVG后功率因数从0.85回到0.99
运维·人工智能·自动化
..Dauntless..13 小时前
【Linux】一切皆文件和缓冲区
linux·运维·服务器
QMCY_jason13 小时前
x86 ubuntu2204 无gui 安装 openeuler 2203 aarch64版本
linux·运维·服务器