Linux Day10 ---Mybash
目录
一、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等命令
相关文章:

Linux Day10 ---Mybash
目录 一、Mybash介绍 1.1.mybash.c 打印函数 分割函数 命令函数 二、Mybash实现 2.1.打印函数 2.1.1需要使用到的功能函数 1.获取与当前用户关联的UID 2.获取与当前用户的相关信息---一个结构体(passwd) 3.获取主机信息 4.获取当前所处位置 5.给…...
Flask-Sockets和Flask-Login联合实现websocket的登录认证功能
flask_login 提供了一个方便的方式来管理用户会话。当你在 Flask 的 HTTP 视图中使用它时,你可以简单地使用 login_required 装饰器来确保用户已登录。 但是,flask_sockets 并没有直接与 flask_login 集成。如果你想在建立 WebSocket 连接时检查用户是否…...

东盟全面覆盖?长城战略部署核心区域市场,首个百万粉丝国产品牌
根据最新消息,长城汽车在东南亚地区取得了巨大的成功,成功进军了亚洲最大的汽车市场之一-印度尼西亚。这标志着长城汽车已经实现了东盟核心市场的全面覆盖,成为全球布局的重要一步。 在过去的几年里,长城汽车在东盟地区的市场布局…...

基于PHP的电脑商城系统
有需要请加文章底部Q哦 可远程调试 基于PHP的电脑商城系统 一 介绍 此电脑商城系统基于原生PHP开发,数据库mysql,前端bootstrap。用户可注册登录,购物下单,评论等。管理员登录后台对电脑商品,用户,订单&a…...

无客户端网络准入方案,为集成电路企业终端管理开启省事更省心模式
宁盾无客户端网络准入控制方案正在成为先进制造、高科技互联网企业等创新型客户的优选方案。创新型客户以技术密集型、研发人员占比高著称,在进行网络准入建设时,如何平衡好用户体验与顺利达成项目预期之间的矛盾,是创新企业 IT 安全团队格外…...

5G与4G的RRC协议之异同
什么是无线资源控制(RRC)? 我们知道,在移动通信中,无线资源管理是非常重要的一个环节,首先介绍一下什么是无线资源控制(RRC)。 手机和网络通过无线信道相互通信,彼此交…...

横扫“盲区”、“看透”缺陷,维视智造推出短波红外相机
在可见光领域,工业相机的视觉应用已经十分成熟,但在日常的客户咨询中,我们也经常接到一些“超纲需求”——客户想要检测“白底上的白色缺陷”、“不透明包装内的透明物体有无”等,均属于可见光无法实现的检测,而市面上…...
cgo踩坑:交叉编译过程出现的问题could not determine kind of name for C.XXX
尝试了网上的几种解决方法,都不行,现总结起来: 确认 /* #include <stdio.h> */ import "C"不要有空行 确认你引用的头文件存在(stdio.h这种编译器自带的不需要你确认) 如果引用了多个包,…...
自然语言处理(NLP)技术的例子
以下是几个自然语言处理(NLP)技术的例子: 机器翻译:机器翻译是将一种自然语言的文本转换成另一种语言的文本的过程。这种技术应用于在线翻译器、多语言聊天机器人、多语言搜索引擎等地方。 文本分类:文本分类将文本分…...

Python“牵手”义乌购商品列表数据,关键词搜索义乌购API接口数据,义乌购API接口申请指南
义乌购平台API接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范,义乌购API接口是指通过编程的方式,让开发者能够通过HTTP协议直接访问义乌购平台的数据,包括商品信息、店铺信息、物流信息等,从而实现义…...
ip_vs 原理解析 (四)hook 后的开始 NF_INET_LOCAL_IN
文章目录 ip_vs hook 后NF_INET_LOCAL_IN 本章重点: k8s 如何利用 ip_vs 实现源 IP 会话亲和性。 ip_vs hook 后 NF_INET_LOCAL_IN 根据优先级依次是 ip_vs_reply4,ip_vs_remote_request4 ip_vs_reply4| -- ip_vs_out| -- skb_to_full_sk(skb…...
分布式之CAP理论与BASE理论
CAP理论 CAP:一致性(consistency)、可用性(Availability)、分区容错(partition-tolerance)。CAP定律说的是在一个分布式计算机系统中,一致性,可用性和分区容错性这三种保证无法同时…...
Java之初始化顺序实践
功能概述 在创建Java对象时,需要将对象中的成员变量进行初始化后,才能调用对象的构造方法创建对象。本文中将会讲解初始化时父类与子类对应的顺序。 功能实践 场景1:父类、子类的初始化顺序 用例代码 Test public void test_init_order(…...
静态库与动态链接库,第三方库集成到VS
目录 介绍静态库与动态链接库静态库动态链接库 如何将第三方库集成到VS上VS属性管理器配置静态库配置动态链接库属性管理器其他的内容MKL库的安装boost库的安装 介绍 众所周知,.c文件或者.cpp文件变成.exe文件需要经历四个过程 分别是预处理,编译&#…...

生态经济学领域里的R语言机器学(数据的收集与清洗、综合建模评价、数据的分析与可视化、数据的空间效应、因果推断等)
近年来,人工智能领域已经取得突破性进展,对经济社会各个领域都产生了重大影响,结合了统计学、数据科学和计算机科学的机器学习是人工智能的主流方向之一,目前也在飞快的融入计量经济学研究。表面上机器学习通常使用大数据…...
【ROS】自定义消息方面的bug总结(1)
根据需要创建功能包 一类引用ros库函数的一类是自己定义的消息类型 库函数中有的可以直接在创建功能包的时候添加依赖,也可以在CMakeLists.txt中手动添加 catkin_create_pkg crepes roscpp rospy std_msgs nav_msgs sensor_msgs geometry_msgs创建文件夹msg…...

CTF-XXE(持续更新,欢迎分享更多相关知识点的题目)
知识 实例 BUU [PHP]XXE 进来看到 然后一起看 Write BUU XXE COURSE 1 进来看到 一起看 write NSS [NCTF2019]Fake XML cookbook 反正是XXE 直接整 write [NCTF 2019]True XML cookbook 不整花里胡哨,解题在最下面 write 与博主不同,我通过…...

Python工具箱系列(四十一)
使用zip批量压缩文件 前文的代码示例了使用gzip对单个文件进行压缩。本文示例使用更通用的zipfile来批量压缩文件。zipfile也是python内置的库,使用起来非常方便。废话不说,直接上代码示例。 import dbm import glob import zipfile# 保存压缩计划的库名…...

Bigemap在路桥行业是怎么应用的?
选择Bigemap的原因: 奥维下架了,后来了解到的bigemap,于是测试了这款软件 使用场景: 下载影像、矢量路网做前期策划,下载完数据后导出cad ,做一些标注,最终出图下载等高线,作为前期选址依据 …...
代码随想录算法训练营Day48 || ● 198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III
问题1:198. 打家劫舍 - 力扣(LeetCode) 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...

算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...

CTF show 数学不及格
拿到题目先查一下壳,看一下信息 发现是一个ELF文件,64位的 用IDA Pro 64 打开这个文件 然后点击F5进行伪代码转换 可以看到有五个if判断,第一个argc ! 5这个判断并没有起太大作用,主要是下面四个if判断 根据题目…...