做网站大概要多少,wordpress 说说 分页,wordpress域名自动重复,扫wordpress后台#x1f466;个人主页#xff1a;Weraphael ✍#x1f3fb;作者简介#xff1a;目前正在学习c和算法 ✈️专栏#xff1a;Linux #x1f40b; 希望大家多多支持#xff0c;咱一起进步#xff01;#x1f601; 如果文章有啥瑕疵#xff0c;希望大佬指点一二 如果文章对… 个人主页Weraphael ✍作者简介目前正在学习c和算法 ✈️专栏Linux 希望大家多多支持咱一起进步 如果文章有啥瑕疵希望大佬指点一二 如果文章对你有帮助的话 欢迎 评论 点赞 收藏 加关注 目录 前言一、用户输入二、指令分割三、程序替换3.1 外部命令3.2 内建命令3.2.1 cd3.2.2 export3.2.3 echo 四、总结及源码 前言
简单回顾一下往期知识命令行解释器bash只是一个”外壳程序而操作系统则称为“内壳程序”这是因为操作系统不相信用户因此我们用户只能通过“外壳程序”将指令进行翻译给操作系统操作系统再将结果通过“外壳程序”返回给用户。 以上图片来自于【往期博客】
由于目前学习到的知识有限后面会慢慢更新相关接口 ~
一、用户输入
首先命令行bash需要提示类似于[用户名主机名 当前目录]$。我们可以使用以下系统调用接口来获取它们
获取用户名
#include unistd.h
char *getlogin();获取主机名
#include unistd.h
int gethostname(char *name, size_t len);其中 该函数的功能是将主机名复制到 name 指向的缓冲区中字符数组注意name 缓冲区应该足够大以容纳主机名。 第二个参数len 是缓冲区的长度数组长度。 返回值 成功返回0并将主机名复制到 name 指向的缓冲区中。失败返回 -1。
获取当前工作目录路径
#include unistd.h
char *getcwd(char *buf, size_t size);其中 该函数的功能是将当前工作目录的绝对路径复制到 buf 指向的缓冲区中并保证以空字符 \0 结尾。注意传递给 getcwd() 的缓冲区应该足够大。 size 参数表示缓冲区的大小。 函数的返回值 如果成功 buf 指向的缓冲区地址。如果失败返回 NULL。
有了以上接口我们就可以用代码来实现了 接下来就应该轮到用户输入指令本质就是输入字符串。
这里需要注意的是由于我们输入的指令可以带选项那么必定是带空格的如ls -al而 scanf默认遇到空格或者换行就不读取了。除非你使用修饰符配合scanf函数
char str[100];
scanf(%[^\n], str); // 可以读空格和换行除以上方法以外fgets函数也可以读取空格和换行
#include stdio.h
char *fgets(char *s, int size, FILE *stream);其中
第一个参数用于存储从输入流中读取的数据。一般是一个字符数组。第二个参数计算整个字符数组的大小。第三个参数这个参数指定了从哪个文件流中读取数据。在大多数情况下我们使用标准输入流即键盘输入因此会传递stdin。返回值读取数据成功时返回一个指向目标缓冲区的指针如果读取失败或者到达文件结尾时返回NULL。 以上程序还有缺陷那就是当我们输入完一条指令后bash把结果返回给我们后会继续重复提示我们输入指令。而我们目前写的程序执行完一条指令后就退出进程。因此以上程序应当是一个循环。 二、指令分割
当用户输入完指令我们要进行指令分割为后面【程序替换】做准备。
由于一开始我们使用fgets函数将最后的回车\n给读取到了command数组因此我们要将其去掉置为\0即可 接下来我们进行分割命令行参数C语言提供了字符串分割函数 strtok。当然你也可以自己手撕一个hh
#include string.h
char *strtok(char *str, const char *delim);其中
str要分割的字符串第一次调用时传入待分割的字符串后续调用传NULL继续分割该字符串函数会继续在上一次调用的字符串中查找下一个标记的位置。delim分隔符的字符串即用来确定标记边界的字符集合。strtok() 函数返回一个指向分割后的标记的指针如果没有找到标记则返回NULL。 三、程序替换
3.1 外部命令
对于外部命令shell则会创建一个子进程并在子进程中进行程序替换来执行这些命令。在执行完成后Shell会等待子进程退出并获取子进程的退出码。 如上所示有很多替换函数供我们选择为了方便尽量不要选择带l因为我们已经将命令行参数分割好了在字符指针数组argv中而无需一一列举另外我们也不要选择不带p的因为这样还需要我们自己去写完整的文件路径。
综上我们可以使用execvpe函数。另外environ是全局变量它是由标准C库提供的当用户登录时shell会读取用户目录下的.bash_profile文件里面保存了导入环境变量的方式。 如上所示我们执行的命令确实起效了但是还是有些缺陷比如ls显示出来的文件没有高亮以及ll(ls -l重命名没有效果因此我们的代码还是可以再改造改造。
我们可以先来解决ls显示的文件没有高亮的问题 因此我们只需要对argv数组添加一个命令行参数也就是--colorauto即可 最后来解决ll未显示出结果的问题。 3.2 内建命令
什么是内建命令呢比如以cd为例子进程执行cd命令改变了子进程的工作目录由于父子进程是相互独立的子进程改变了而父进程bash却没有影响。因此内建命令是不需要通过创建子进程来执行。
Linux中有很多内建命令 这里我只挑选一些来完善
3.2.1 cd
我们可以使用系统调用接口chdir函数来改变当前进程的工作目录并且它对于特殊的路径 .. 也可以完成对应的更改但除了cd ~和cd -分别是返回家目录和返回最近一次访问的目录注意家目录和最近一次访问目录可以通过环境变量来获取。 但需要注意的是改变当前进程的工作目录不会直接影响环境变量 PWD我们需要手动更新。以上环境变量只截取了部分
步骤如下 调用getcwd函数更新pwd数组 将pwd替换掉原来环境变量PWD的值即可
我们可以使用sprintf函数来替换。sprintf 函数是 C 语言中的一个标准库函数用于将格式化的数据写入一个字符串中。
#include stdio.h
int sprintf(char *str, const char *format, ...);其中
str 是一个指向字符数组的指针指向需要修改的字符串后面的参数就和printf函数一样了 以上环境变量只截取了部分
3.2.2 export
这个看似非常简单比如添加环境变量export x333那么直接使用putenv(argv[1])其中argv[0]表示exportargv[1]表示x333
如果你是以上这样做法导致第一次添加可能成功但第二次添加后第一次添加的就没了。这是因为argv[1] 中的内容是不断变化的第二次添加就覆盖了第一次添加。
正确做法 一般用户自定义的环境变量在 bash 中需要用户自己维护一个字符指针数组。 先将待添加的环境变量拷贝至指针数组 再从中读取并调用 putenv 函数添加至环境变量表 3.2.3 echo
echo首先需要能获取最近一次进程的退出状态 本应当返回ls进程的退出状态而他原原本本返回了$? 我们打印环境变量例如$PATH会出现什么都没输出的现象 输出字符串会带双引号的情况 四、总结及源码
所谓的shell也是一个进程它可以获取用户的输入然后对用户的输入做分析。对于内建命令shell会直接调用函数来执行而对于外部命令shell则会创建一个子进程并在子进程中进行进程替换来执行相对应的命令。在执行完成后shell会等待子进程退出并获取子进程的退出码。
获取源码点击跳转