Linux Day10 ---Mybash

news2024/9/26 1:27:03

目录

一、Mybash介绍

1.1.mybash.c

    打印函数

    分割函数

    命令函数

二、Mybash实现

2.1.打印函数

2.1.1需要使用到的功能函数

1.获取与当前用户关联的UID

2.获取与当前用户的相关信息---一个结构体(passwd)

3.获取主机信息

4.获取当前所处位置

5.给对应字体加颜色

2.1.2 打印函数实现

2.2 分割函数

2.2.1 strtok函数

2.2.2分割函数实现

 2.3 命令函数

2.3.1 exit

2.3.2 clear

 2.3.3 cd

2.3.4 chmod

2.3.5 pwd

2.3.6 mkdir

2.3.7 rmdir

2.3.8 rm

2.3.9 复制、更新进程

三、使用看效果


一、Mybash介绍

1.1.mybash.c

    这个函数用来实现mybash,可分为三大部分:打印函数、分割函数、命令函数

    打印函数

打印出如下的功能
   

能够和bash一样显示出用户+主机名+当前目录+用户身份

    分割函数

将输入的命令按空格分割,并保存到相应的数组中,使用到strtok()字符分割函数。

    命令函数

根据exec系列学习,采用fork+exec,父进程等待,子进程采用exec,调用自己实现的命令文件,进行真实命令的模拟

二、Mybash实现

2.1.打印函数

2.1.1需要使用到的功能函数

1.获取与当前用户关联的UID

uid_t getuid(void);

如果得到是0,就是管理员,初始为普通用户。

2.获取与当前用户的相关信息---一个结构体(passwd)

passwd成员                   说明

char* pw_name           用户登录号

uid_t pw_uid                UID号

gid_t pw_gid                GID号

char* pw_dir                用户家目录

char* pw_gecos          用户全名

char* pw_shell            用户默认shell

 struct passwd*getwuid(uid_t uid);

这里可以定义一个相对应类型的指针ptr去指向该结构体,进而->方式访问到该用户的UID号

3.获取主机信息

int gethostname(char*name,size_t namelen);

gethostname函数把机器的主机名写入到name字符串里,该字符串至少有namelen个字符长。而成功,gethostname的返回0,否则返回-1。

4.获取当前所处位置

char*getcwd(char*buf,size_t size);

getcwd函数把当前目录的名字写入给定的缓冲区-buf,如果目录名长度超出参数size给出的缓冲区长度,就返回NULL,如果成功,返回指针buf。

5.给对应字体加颜色

详细参考printf函数中的/033一系列。

2.1.2 打印函数实现

void print_info()
{
    uid_t uid=getuid();
    char*s="$";
    if(uid==0)
    {
        s="#";
    }
    struct passwd* ptr=getpwuid(uid);
    if(ptr==NULL)
    {
        printf("mybash 1.0 $");
        fflush(stdout);
        return;
    }
    char hostname[128]={0};
    if(gethostname(hostname,128)==-1)
    {
       printf("mybash 1.0 $");
       fflush(stdout);
       return;
     }
    char curr_dir[256]={0};
    if(getcwd(curr_dir,256)==NULL)
    {
        printf("mybash 1.0 $");
        fflush(stdout);
        return;
    }
     printf("\033[1;32m%s@%s\033[0m\033[1;34m:%s\033[0m %s ",ptr->pw_name,hostname,curr_dir,s);
    fflush(stdout);
    return;
}

2.2 分割函数

2.2.1 strtok函数

char* strtok(char*str,const char*delim);

str为需要分割的字符串,delim为分割标记。

通常需要循环使用,如果需要多次分割当前字符串,在第二次使用的时候字符串那使用NULL,系统会认为继续对当前字符串进行分割(这里有个指针会指向第一次分割完后的位置)。

2.2.2分割函数实现

char* get_cmd(char buff[],char*myargv[])
{
    if(buff==NULL||myargv ==NULL)
    {
        return NULL;
    }
    int i=0;
    char*s=strtok(buff," ");
    while(s!=NULL)
    {
        myargv[i++]=s;
        s=strtok(NULL," ");
    }
    return myargv[0];
}

 2.3 命令函数

2.3.1 exit

exit表示退出当前进程。

if(strcmp(cmd,exit)==0)
    {
        break;
    }

2.3.2 clear

clear表示清屏,并将光标放置在最上方最左边位置

  \033[2J   清屏  

  \033[y;xH设置光标位置 

    if(strcmp(cmd,"clear")==0)
        {
            printf("/033[2J]\033[0;0H");
        }

 2.3.3 cd

首先先说下myargv就是argv,在前面的文里说过int main(int argc,char*argv[],char*envp[]),这里的myargv里面就存储了需要切换到的路径。

其次,程序可以像用户在文件系统里那样来切换目录,就像在shell里面使用cd命令来切换目录一样。程序使用的是chdir系统调用。

int chdir(const char*path);

这里的path存储在myargv[1]里面,myargv[0]为命令cd .

成功返回0,失败返回-1

if(strcmp(cmd,"cd")==0)
        {
            if(myargv[1]!=NULL)
            {
                if(chdir(myargv[1])==-1)
                {
                    perror("cd err\n");
                }
            }
            continue;
        }

2.3.4 chmod

首先先来看看shell里面的chmod

第一个参数为权限设置,第二个参数为需要修改的文件

所以我们通过查看书,可以发现chmod的系统调用

int chmod(const char*path,mode_t mode);

path参数指定的文件被修改为具有mode参数给出的访问权限。

注意我们这里的参数为8进制,所以涉及到参数进制转换。

 if(strcmp(cmd,"chmod")==0)
        {
            const char*path=myargv[2];
            int  mode=atoi(myargv[1]);
            int mode_1=mode/10/10;
            int mode_3=mode%10;
            int mode_2=mode/10%10;
            mode=mode_1*8*8+mode_2*8+mode_3;
            if(chmod(path,mode)<0)
            {
                printf("chmod err\n");
            }
            continue;
        }

2.3.5 pwd

getcwd在上面的打印函数中提过,详细请参考上面。

if(strcmp(cmd,"pwd")==0)
        {
            char cwd[128]={0};
            if(getcwd(cwd,128)==NULL)
            {
                printf("pwd err\n");
                continue;
            }
            printf("%s\n",cwd);
            continue;
        }

2.3.6 mkdir

mkdir系统调用用于创建目录,他相当于mkdir程序。mkdir调用将参数path作为新建目录的名字。目录的权限由参数mode设定,将含义按open系统调用的O_CREAT选项的有关定义设置。

int mkdir(const char* path,mode_t mode);

注意mode数值的设定。

 if(strcmp(cmd,"mkdir")==0)
        {
            char* path=myargv[1];
            mode_t mode=7*8*8+7*8+5;
            if(mkdir(path,mode)==-1)
            {
                printf("mkdir err\n");
            }
            continue;
        }

2.3.7 rmdir

rmdir系统调用用于删除目录,但只有在目录为空才行,rmdir程序就是用这个系统调用来完成工作的。

int rmdir(const char*path);

if(strcmp(cmd,"rmdir")==0)
        {
            char*path=myargv[1];
            DIR* dir = opendir("path");
            if(dir == NULL){
                 perror("打开目录失败");
                 exit(1);
            }
            struct dirent *ptr = NULL;
            while((ptr=readdir(dir))!=NULL);
            if(ptr == NULL){
                rmdir(myargv[1]);
            }
            continue;
        }

这里我先通过调用opendir和readdir两个函数来判断当前目录是否为空,进而使用rmdir函数来删除当前目录。

opendir函数的作用是打开一个目录并建立一个目录流,成功返回一个指向DIR结构的指针,该指针用于读取目录数据项,失败则返回一个空指针。

DIR*opendir(const char*name);

然后继续使用readdir()函数,返回一个指针,该指针指向结构里面保存着目录流dirp中下一个目录项的有关资源,后续的readdir调用返回后续的目录项,如果错误或者到达目录尾则返回NULL。

因此使用了while循环。

2.3.8 rm

rm可以直接删除普通目录文件,但是不能直接删除普通文件,需要使用到rm -r

因此这里我们需要获取到当前文件的类型

文件的类型存储在struct stat

 

 if(strcmp(cmd,"rm")==0)
        {
            char*path1=myargv[1];
            char*path2=myargv[2];
            struct stat buf;
            char * ptr;
            int result;
            result = stat(myargv[3], &buf);
            if(S_ISREG(buf.st_mode))
            {
                if(strcmp(cmd,strcat(path1,path2))==0)
                {
                    unlink(myargv[3]);
                }
            }
            if(S_ISDIR(buf.st_mode))
            {
                rmdir(myargv[3]);
            }
        }

如果是普通文件,我们使用unlink系统调用删除一个文件。

unlink系统删除一个文件的目录项并减少他的链接数,它成功返回0失败返回-1.

如果想通过这个函数成功删除文件,你就必须拥有该文件所属目录的写和执行权限。

2.3.9 复制、更新进程

pid_t pid=fork();
        if(pid==-1)
        {
            printf("fork err\n");
            continue;
        }
        if(pid==0)
        {
            execvp(cmd,myargv);
            printf("exec err\n");
            exit(0);
        }
        wait(NULL);

剩余命令我们后续更新。。。。敬请期待

接下来我们看一下效果

三、使用看效果

 

下次我们更新touch ,mv,cp,ls,cat等命令

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/921635.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

论文阅读 FOCUS-AND-DETECT: A SMALL OBJECT DETECTION FRAMEWORK FOR AERIAL IMAGES

文章目录 FOCUS-AND-DETECT: A SMALL OBJECT DETECTION FRAMEWORK FOR AERIAL IMAGESABSTRACT1 Introduction2 Related Work3 Focus-and-Detect3.1 Overview3.2 Focus Stage3.2.1 Generating Ground-Truth Boxes of Focal Regions Using Gaussian Mixture Model 3.3 Detection …

物种气候生态位动态量化与分布特征模拟

在全球气候快速变化的背景下&#xff0c;理解并预测生物种群如何应对气候变化&#xff0c;特别是它们的地理分布如何变化&#xff0c;已经变得至关重要。利用R语言进行物种气候生态位动态量化与分布特征模拟&#xff0c;不仅可以量化描述物种对环境的需求和适应性&#xff0c;预…

StableVideo:使用Stable Diffusion生成连续无闪烁的视频

使用Stable Diffusion生成视频一直是人们的研究目标&#xff0c;但是我们遇到的最大问题是视频帧和帧之间的闪烁&#xff0c;但是最新的论文则着力解决这个问题。 本文总结了Chai等人的论文《StableVideo: Text-driven consistency -aware Diffusion Video Editing》&#xff…

高性能网络模式-Reactor

事实上&#xff0c;Reactor 模式也叫Dispatcher模式&#xff0c;即I/O 多路复⽤监听事件&#xff0c;收到事件后&#xff0c;根据事件类型分配&#xff08;Dispatch&#xff09;给某个进程/线程。Reactor 模式也是一种非阻塞同步网络模式。 Reactor 模式主要由 Reactor部分和处…

Django基础3——视图函数

文章目录 一、基本了解1.1 Django内置函数1.2 http请求流程 二、HttpRequest对象&#xff08;接受客户端请求&#xff09;2.1 常用属性2.2 常用方法2.3 服务端接收URL参数2.4 QueryDict对象2.5 案例2.5.1 表单GET提交2.5.2 表单POST提交2.5.3 上传文件 三、HttpResponse对象&am…

NV PTX ISA 文档的增量说明

无它&#xff0c;维截图尔&#xff0c;汇总一下&#xff0c;找找规律&#xff1b; cuda 12.0 PTX 8.0 关键字&#xff1a; 从cuda 8.0开始&#xff1a; 显然&#xff0c;每次增量的主要因素是对应着对新的硬件功能的提炼&#xff1b;

构建 NodeJS cinema API 网关并部署到 Docker(04/4)

一、说明 构建一个微服务的电影网站&#xff0c;需要Docker、NodeJS、MongoDB&#xff0c;这样的案例您见过吗&#xff1f;如果对此有兴趣&#xff0c;您就继续往下看吧。 我们前几章的快速回顾 第一篇文章介绍了微服务架构模式&#xff0c;并讨论了使用微服务的优缺点。第二篇…

Unity报错DllNotFoundException:sqlite3

Unity项目中要使用轻型数据库sqlite&#xff0c;除了导入sqlite3.dll外&#xff0c;还需要导入Mono.Data.Sqlite.dll和System.Data.dll&#xff08;工程里或者编辑器里面有System.Data.dll时就不需要&#xff09;两个文件。 如果在编辑器中运行出现 “DllNotFoundException:sql…

pyside6最小化的核心调用代码

pyside6最小化的核心调用代码&#xff1a; 一、格式代码 你认为是 制式代码&#xff0c;下面图中的就是核心代码&#xff0c;以后就是这样记住以及使用即可 二、图形代码【生成代码】 2.1designer设计界面 2.2设计的界面转换为代码 注意图纸划线的地方&#xff0c;后续导入…

卓码软件测评简析:软件压力测试工具和流程有哪些?

在软件开发过程中&#xff0c;压力测试是非常重要的一项工作&#xff0c;它可以帮助客户评估软件系统在正常或异常负载下的性能表现。在这个领域&#xff0c;有很多不同的工具可供选择&#xff0c;每个工具具有其独特的特点和优势。那么常见的压力测试工具有哪些以及进行压力测…

外网访问家里虚拟机的两种方法

从外网访问家里虚拟机的两种方法 起因 在公司&#xff0c;当我不想干的时候就想着跑路&#xff0c;但是自己又太菜了&#xff08;饭碗要紧&#xff09;&#xff0c;所以想通过ssh登录到自己的家里一台linux上&#xff0c;去敲一敲 linux命令&#xff0c;sql命令&#xff0c;do…

Mobx在非react组件中修改数据,在ts/js中修改数据实现响应式更新

我们都之前在封装mobx作为数据存储的时候&#xff0c;使用到了useContext作为包裹&#xff0c;将store变成了一个hooks使用&#xff0c;封装代码: import React from react import UserInfo from ./user import Setting from ./seting import NoteStore from ./noteclass Stor…

WSL(centos7.0.1907.3)安装lxc

安装 1.centos的epel源提供了lxc的安装包&#xff0c;在使用epel源时首先安装epel-release包&#xff1a; yum -y install epel-release2.安装lxc软件包和依赖包 yum -y install lxc lxc-templates bridge-utils lxc-libs libcgroup libvirt 安装完成后&#xff0c;通过 lx…

centos安装redis教程

1.下载安装包 redis官网 下载最新版本redis安装包 2.上传到服务器 然后解压 解压命令 tar xzvf redis-7.2.0.tar.gz 进入文件夹 cd redis-7.2.0 执行安装编译命令 make 如果要安装到别的目录则执行 make install PREFIX/目录地址 看到如下内容则说明安装成功 如有遇到报错…

骨传导蓝牙耳机能打电话吗,骨传导蓝牙耳机别人听得到吗

时光荏苒&#xff0c;社会不断发展&#xff0c;年轻人的生活离不开一样必备神器——耳机。而在众多耳机中&#xff0c;骨传导耳机备受青睐。这种耳机的佩戴方式不仅方便&#xff0c;还更安全&#xff0c;能有效降低中耳炎的风险。此外&#xff0c;经过精心设计的耳机还能有效减…

再升级!PP-OCRv4多场景平均精度提升5%!

OCR方向的工程师&#xff0c;一定有在关注PaddleOCR这个项目&#xff0c;其主要推荐的PP-OCR算法更是被国内外企业开发者广泛应用。短短几年时间&#xff0c;PP-OCR累计Star数量已超过32.2k&#xff0c;频频登上GitHub Trending和Paperswithcode日榜月榜第一&#xff0c;称它为…

Navicat for Mysql 显示 emoji 表情符号乱码问题 — 其它乱码情况都可参考

系统环境&#xff1a; 操作系统&#xff1a;MAC OS 10.11.6 MySQL&#xff1a;Server version: 5.6.21 MySQL Community Server (GPL) Navicat for MySQL: version 9.3.1 - standard 1、问题发现 在客户端执行用户注册&#xff0c;用户名包括 emoji 表情符号&#xff0c;注册完…

SpringBoot基于AOP注解方式实现Redis缓存

一、前言 Spring中的AOP&#xff08;Aspect Oriented Programming&#xff09;是基于代理的AOP实现&#xff0c;通过使用基于代理的技术&#xff0c;可以在不修改原有代码的情况下&#xff0c;对原有代码进行增强和改进。Spring AOP实现了面向切面编程的功能&#xff0c;将横切…

电工-捡测电动机绕组首尾端的电路接线图

电工捡测电动机绕组首尾端的电路接线图 若三相电动机绕组首尾端接错&#xff0c;电动机起动时&#xff0c;会引起振动、噪声、三相电流严重不平衡、电动机过热、转速降低&#xff0c;甚至电动机不转等故障。 可用交流电源和灯泡来检查电动机三相绕组的首尾端用以检测电动机首尾…

Vue3项目实战

目录 一、项目准备 二、基础语法应用 2.1、mixin应用 2.2、网络请求 2.3、显示与隐藏 2.4、编程式路由跳转 2.5、下载资料 2.6、调用方法 2.7、监听路由变化 2.8、pinia应用 (1)存储token(user.js) (2)全选全不选案例(car.js) 一、项目准备 下载&#xff1a; cnp…