当前位置: 首页 > news >正文

shell的编写

文章目录

  • 1.框架
  • 2.命令行
  • 3.获取用户命令字符串
  • 4.命令行字符串分割
  • 5.执行命令和内建命令
  • 6.完整代码:


1.框架

我们知道shell是一直存在的,所以首先我们第一步就是要搭建一个框架,使其一直存在。
那么也很简单,一个while循环就可以完成。
在这里插入图片描述

2.命令行

我们的shell最前面都是有一个命令行的在这里插入图片描述
。如下图:

那么命令行我们应该怎么获取呢?我们可以从环境变量中获取,env查看环境变量。
getenv函数就可以帮我们获取环境变量,可以获取用户名、地址等等!
getenv获取成功就会取到那个对象,如果获取失败就会返回空!!
在这里插入图片描述
然后我们需要把上面获取到的三个字符拼接在一起,这时候就需要用到snprintf函数了:
在这里插入图片描述

在这里插入图片描述

到这里,第一步就结束了!

3.获取用户命令字符串

这一步我们需要获取,命令字符串,因为有空格。我们无法使用scanf。这里使用fgets
在这里插入图片描述
在这里插入图片描述

4.命令行字符串分割

在这里插入图片描述
分割思路:
在这里插入图片描述
具体分割我们可以使用strtok函数
在这里插入图片描述
但是这里有个需要注意的地方,strtok的第二参数需要是一个字符串!!
在这里插入图片描述

5.执行命令和内建命令


内建命令:
在这里插入图片描述

6.完整代码:

以上就是编写shell的大致思路了!上面的shell为了和系统本身的shell做区分,所以前的路径都是绝对路径,一长串。在这里插入图片描述
myshell.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 SIZE 512
#define ZERO '\0'
#define SEP " " 
#define NUM 32// 为了方便,我就直接定义了
char cwd[SIZE*2];
char *gArgv[NUM];
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;
}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 MakeCommandLineAndPrint()
{char line[SIZE];const char *username = GetUserName();const char *hostname = GetHostName();const char *cwd = GetCwd();snprintf(line, sizeof(line), "[%s@%s %s]> ", username, hostname, cwd);printf("%s", line);fflush(stdout);
}void SplitCommand(char command[], size_t n)
{(void)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){// childexecvp(gArgv[0], gArgv);exit(errno);}else{// fahterint 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); // OK
}int CheckBuildin()
{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()
{//首先,自己写的shell需要一直存在,所以设置一个while循环
int quite=0;
while(!quite)
{// 1. 我们需要自己输出一个命令行MakeCommandLineAndPrint();// 2. 获取用户命令字符串char usercommand[SIZE];int n = GetUserCommand(usercommand, sizeof(usercommand));if(n <= 0) return 1;// 3. 命令行字符串分割. SplitCommand(usercommand, sizeof(usercommand));// 4. 检测命令是否是内建命令n = CheckBuildin();if(n) continue;
// 5. 执行命令ExecuteCommand();}return 0;
}

相关文章:

shell的编写

文章目录 1.框架2.命令行3.获取用户命令字符串4.命令行字符串分割5.执行命令和内建命令6.完整代码&#xff1a; 1.框架 我们知道shell是一直存在的&#xff0c;所以首先我们第一步就是要搭建一个框架&#xff0c;使其一直存在。 那么也很简单&#xff0c;一个while循环就可以完…...

css心跳动画

图标引入 <img class"icon" src"heart.svg" alt"" srcset""> CSS代码 <style>.icon {animation:bpm 1s linear,pulse 0.75s 1s linear infinite;}keyframes pulse {from,75%,to {transform: scale(1);}25% {transform:…...

在 Amazon Timestream 上通过时序数据机器学习进行预测分析

由于不断变化的需求和现代化基础设施的动态性质&#xff0c;为大型应用程序规划容量可能会非常困难。例如&#xff0c;传统的反应式方法依赖于某些 DevOps 指标&#xff08;如 CPU 和内存&#xff09;的静态阈值&#xff0c;而这些指标在这样的环境中并不足以解决问题。在这篇文…...

【智能排班系统】快速消费线程池

文章目录 线程池介绍线程池核心参数核心线程数&#xff08;Core Pool Size&#xff09;最大线程数&#xff08;Maximum Pool Size&#xff09;队列&#xff08;Queue&#xff09;线程空闲超时时间&#xff08;KeepAliveTime&#xff09;拒绝策略&#xff08;RejectedExecutionH…...

C语言——内存函数

前言&#xff1a; C语言中除了字符串函数和字符函数外&#xff0c;还有一些函数可以直接对内存进行操作&#xff0c;这些函数被称为内存函数&#xff0c;这些函数与字符串函数都属于<string.h>这个头文件中。 一.memcpy&#xff08;&#xff09;函数 memcpy是C语言中的…...

ideaSSM图书借阅管理系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 SSM 图书借阅管理系统是一套完善的信息管理系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码 和数据库&#xff0c;系统主…...

普联一面4.2面试记录

普联一面4.2面试记录 文章目录 普联一面4.2面试记录1.jdk和jre的区别2.java的容器有哪些3.list set map的区别4.get和post的区别5.哪个更安全6.java哪些集合类是线程安全的7.创建线程有哪几种方式8.线程的状态有哪几种9.线程的run和start的区别10.什么是java序列化11.redis的优…...

SQLite的架构(十一)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite下一代查询规划器(十&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 介绍 本文档介绍SQLite库的架构。 这里的信息对那些想要了解或 修改SQLite的内部工作原理。 接口SQL 命令处理器虚拟机B-树…...

Vue2电商前台项目(一):项目前的初始化及搭建

一、项目初始化 创建项目&#xff1a;sudo vue create app 1.项目配置 &#xff08;1&#xff09;浏览器自动打开 在package.json文件中&#xff0c;serve后面加上 --open "scripts": {"serve": "vue-cli-service serve --open","buil…...

4.6 offset指令,jmp short指令,far,dword ptr各种跳转指令

4.6 offset指令&#xff0c;jmp short指令&#xff0c;far&#xff0c;dword ptr各种跳转指令 可以修改IP&#xff0c;或同时修改CS和IP的指令统称为转移指令。概括的讲&#xff0c;转移指令就是可以控制CPU执行内存中某处代码的指令 1. 转移指令 1.1 8086CPU的转移行为有以…...

【WEEK5】 【DAY5】DML语言【中文版】

2024.3.29 Friday 目录 3.DML语言3.1.外键&#xff08;了解&#xff09;3.1.1.概念3.1.2.作用3.1.3.添加&#xff08;书写&#xff09;外键的几种方法3.1.3.1.创建表时直接在主动引用的表里写&#xff08;被引用的表的被引用的部分&#xff09;3.1.3.2.先创建表后修改表以添加…...

媒体偏见从何而来?--- 美国MRC(媒体评级委员会)为何而生?

每天当我们打开淘宝&#xff0c;京东&#xff0c;步入超市&#xff0c;逛街或者逛展会&#xff0c;各种广告铺天盖地而来。从原来的平面广告&#xff0c;到多媒体广告&#xff0c;到今天融合AR和VR技术的数字广告&#xff0c;还有元宇宙虚拟世界&#xff0c;还有大模型加持的智…...

Solana 线下活动回顾|多方创新实践,引领 Solana“文艺复兴”新浪潮

Solana 作为在过去一年里实现突破式飞跃的头部公链&#xff0c;究竟是如何与 Web3 行业共振&#xff0c;带来全新的技术发展与生态亮点的呢&#xff1f;在 3 月 24 日刚结束的「TinTin Destination Moon」活动现场&#xff0c;来自 Solana 生态的的专家大咖和 Web3 行业的资深人…...

CSS3 实现文本与图片横向无限滚动动画

文章目录 1. 实现效果2.html结构3. css代码 1. 实现效果 gif录屏比较卡&#xff0c;实际很湿滑&#xff0c;因为是css动画实现的 2.html结构 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"…...

Android 性能优化之黑科技开道(一)

1. 缘起 在开发电视版智家 App9.0 项目的时候&#xff0c;发现了一个性能问题。电视系统原本剩余的可用资源就少&#xff0c;而随着 9.0 功能的进一步增多&#xff0c;特别是门铃、门锁、多路视频同屏监控后等功能的增加&#xff0c;开始出现了卡顿情况。 经过调研分析发现有…...

Successive Convex Approximation算法的学习笔记

文章目录 一、代码debug二、原理 本文主要参考了CSDN上的 另一篇文章&#xff0c;但规范了公式的推导过程和修缮了部分代码 一、代码debug 首先&#xff0c;我们将所有的代码放到MATLAB中&#xff0c;很快在命令行中出现了错误信息 很显然有问题&#xff0c;但是我不知道发生…...

IoT数采平台2:文档

IoT数采平台1&#xff1a;开篇IoT数采平台2&#xff1a;文档IoT数采平台3&#xff1a;功能IoT数采平台4&#xff1a;测试 【平台功能】 基础配置、 实时监控、 规则引擎、 告警列表、 系统配置 消息通知&#xff1a;Websocket 设备上线、设备下线、 数据变化、 告警信息、 实时…...

Vue监听器watch的基本用法

文章目录 1. 作用2. 格式3. 示例3.1 value 值为字符串3.2 value 值为函数3.3 value 值为对象 4. 与计算属性对比 1. 作用 监视数据变化&#xff0c;执行一些业务逻辑或异步操作。 2. 格式 监听器 watch 内部以 key &#xff1a;value 的形式定义&#xff0c;key 是 data 中的…...

MySQL UPDATE JOIN 根据一张表或多表来更新另一张表的数据

当使用MySQL时&#xff0c;经常需要根据一张表或多张表的数据来更新另一张表的数据。这种情况下&#xff0c;我们可以使用UPDATE语句结合JOIN操作来实现这一需求。本文将介绍MySQL中使用UPDATE JOIN的技术。 什么是UPDATE JOIN UPDATE JOIN是MySQL中一种结合UPDATE语句和JOIN…...

JS实现继承的方式ES6版

上一篇&#xff1a;JS实现继承的方式原生版 ES6的继承 主要是依赖extends关键字来实现继承&#xff0c;且继承的效果类似于寄生组合继承。 class Parent() { }class Child extends Parent {constructor(x, y, color) {super(x, y);this.color color;} }子类必须在construct…...

STM32 RTC硬件自检工具CheckRTC:轻量级实时时钟可信度验证

1. 项目概述CheckRTC 是一个面向 STM32 系列微控制器的轻量级 RTC&#xff08;实时时钟&#xff09;模块自检与功能验证程序。其核心目标并非提供通用 RTC 驱动&#xff0c;而是作为嵌入式底层开发中关键的硬件可信度验证工具——在系统启动早期、固件升级后、或长期运行出现时…...

某物APP的newSign与X-Auth-Token逆向分析与实战破解

1. 逆向分析前的环境准备 搞逆向分析的第一步永远是搭建好调试环境。这次我们用的测试机是Pixel 2&#xff0c;系统版本Android 9&#xff0c;目标APP版本v4.82.0。刚开始用Charles抓包时发现什么都抓不到&#xff0c;这其实是APP启用了防抓包机制——具体来说就是设置了Proxy.…...

深度解析ViGEmBus:Windows虚拟游戏手柄驱动实战指南

深度解析ViGEmBus&#xff1a;Windows虚拟游戏手柄驱动实战指南 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus ViGEmBus是一款专业的Windows内核模式驱动&a…...

js06----流程控制

目录 2.4.1、顺序流程控制 2.4.2、分支流程控制 &#xff08;1&#xff09;if分支语句&#xff08;条件判断语句&#xff09; &#xff08;2&#xff09;if....else...语句 需求1&#xff1a; 需求2&#xff1a; &#xff08;3&#xff09;if...else if...else语句&…...

微软服软!被骂5年的Win11将被“整改”:告别强制更新、减少Copilot、任务栏摆放自由

整理 | 屠敏出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;Windows 11 自 2021 年发布以来&#xff0c;因任务栏功能缩水、UI 不统一、强制网络登录以及更高的硬件门槛&#xff0c;成为用户集中吐槽的焦点。再加上近来微软猛推 AI 功能&#xff0c;Copilot 的入口…...

从‘深度学习之美’到TensorFlow 2.9:一个MNIST手写识别项目的实战重构记

1. 当经典教材遇上TensorFlow 2.9&#xff1a;我的MNIST重构历险记 记得第一次翻开《深度学习之美》这本书时&#xff0c;我被其中用TensorFlow实现MNIST手写识别的案例深深吸引。但当我兴冲冲打开电脑准备复现时&#xff0c;却发现书中的TensorFlow 1.x代码在2.9环境下几乎寸步…...

3步彻底解决Umi-OCR Rapid版本HTTP服务无响应问题:参数配置完全指南

3步彻底解决Umi-OCR Rapid版本HTTP服务无响应问题&#xff1a;参数配置完全指南 【免费下载链接】Umi-OCR Umi-OCR: 这是一个免费、开源、可批量处理的离线OCR软件&#xff0c;适用于Windows系统&#xff0c;支持截图OCR、批量OCR、二维码识别等功能。 项目地址: https://git…...

构建全渠道智能通知系统:从高可用架构到用户体验优化

1. 全渠道智能通知系统的核心价值 想象一下这样的场景&#xff1a;你在电商平台下单后&#xff0c;系统立即通过短信发送订单确认通知&#xff1b;当你忘记支付时&#xff0c;APP推送会及时提醒&#xff1b;订单发货后&#xff0c;邮箱里静静躺着物流信息&#xff1b;而站内信则…...

这次终于选对了!高效论文写作全流程一键生成论文工具推荐(2026 最新)

论文写作全流程可拆解为文献调研→选题/开题→大纲/初稿→文献综述→降重/去AI味→润色/格式→查重/投稿七大环节&#xff0c;以下工具按环节精准匹配&#xff0c;兼顾中文适配、降重能力、去AI痕迹、学术合规四大核心需求&#xff0c;覆盖免费/付费、通用/垂直场景。2026年&am…...

BilibiliDown:B站音视频资源管理的全场景解决方案

BilibiliDown&#xff1a;B站音视频资源管理的全场景解决方案 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader &#x1f633; 项目地址: https://gitcode.com/gh_mirrors/bi/Bi…...