首页 > 系统相关 >【Linux】手搓shell

【Linux】手搓shell

时间:2024-04-08 22:02:32浏览次数:25  
标签:shell return int char gArgv Linux const cwd

手搓shell

代码

#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;
}

标签:shell,return,int,char,gArgv,Linux,const,cwd
From: https://blog.csdn.net/W9940/article/details/137525303

相关文章

  • Linux下 sudo 和 su 的区别
    su介绍及使用su命令就是切换用户的工具,比如我们是以普通用户guest登录的,但要添加用户,执行useradd,guest用户没有这个权限,只有root有权限。解决办法有两个,一是退出guest用户,重新以root用户登录;二是不退出guest用户,使用su来切换到root下进行添加用户的操作,操作完......
  • linux环境安装——mysql安装复习
    B站地址:https://www.bilibili.com/video/BV1qS4y1h77S/?spm_id_from=333.337.search-card.all.click&vd_source=79bbd5b76bfd74c2ef1501653cee29d6    下面这个文件和mysql有冲突,需要优先查找并删除:   阿里云系统:cenos7 64位数; 安装包:mysql-8.0.30-linux-g......
  • tomcat弱口令后台getshell漏洞复现
    漏洞描述tomcat是一个用于快速部署jsp网站的中间件tomcat默认的管理页面manager使用basic认证用户名密码登录,可以使用burp进行爆破,并且一般安装后如果不修改/conf/tomcat-users.xml文件中的默认用户名密码tomcat:tomcat,可以登录管理后台,在部署war包后tomcat默认会将war包中的......
  • Linux 性能分析工具大全
    vmstat--虚拟内存统计vmstat(VirtualMeomoryStatistics,虚拟内存统计)是Linux中监控内存的常用工具,可对操作系统的虚拟内存、进程、CPU等的整体情况进行监视。vmstat的常规用法:vmstatintervaltimes 即每隔 interval 秒采样一次,共采样 times 次,如果省略 times,则一直......
  • Linux
    文件权限管理1.Linux用户权限解析我们linux服务器上有严格的权限等级,如果权限过高导致误操作会增加服务器的风险。所以对于了解linux系统中的各种权限及要给用户,服务等分配合理的权限十分重要2.基本权限UGO[root@localhost~]#ll/opt总用量0drwxr-xr-x10root......
  • linux账户
    linux的账户类型有三类linux的uid范围是1-600001超级管理员root02程序用户1-499(centos6以前),1-999(centos7以后)3普通用户500+(centos6以前),1000+(centos7以后)关于账户常用命令who查看当前登录用户信息last命令-x:显示系统开关机以及执行等级信息lastlog查看所有用......
  • Linux应用开发(3):Linux时间操作(time、mktime、localtime等)
    1.简述        在Linux系统中,时间操作函数是编程中经常使用的一部分,它们允许程序获取和设置系统时间,以及对时间进行各种处理。以下是一些常用的时间操作函数的详细介绍。2.时间操作(1)time():获取1970年1月1日以来的总的秒计数        time()函数是时间......
  • Linux curl命令详解
    Linuxcurl命令详解发布时间:2014-10-2710:25:36来源:linux网站作者:linux人命令:curl在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一款很强大的http命令行工具。它支持文件的上传和下载,是综合传输工具,但按传统,习惯称url为下载工具。语法:#curl[op......
  • Linux基本命令入门详解
    Linux基本命令是Linux系统操作的基础,掌握这些命令对于初学者来说至关重要。下面将详细介绍一些常用的Linux基本命令,并附上实际例子。一、目录操作命令pwd:显示当前所在的目录路径。例子:在终端中输入pwd,将显示当前用户所在的目录路径,如/home/user。cd:切换目录。例子:输......
  • Linux命令之lldptool命令
    LLDP是一个数据链路层发现协议,LLDP协议使得接入网络的一台设备可以将其主要的能力,管理地址,设备标识,接口标识等信息发送给接入同一个局域网络的其它设备。lldptool工具采用的是LLDP协议,一般我们使用lldptool是为了得到设备的物理拓扑结构以及管理配置信息,比如说,和eth1网口相连的网......