朋友们、伙计们,我们又见面了,本期来给大家带来一期自定义shell,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!
C 语 言 专 栏:C语言:从入门到精通
数据结构专栏:数据结构
个 人 主 页 :stackY、
C + + 专 栏 :C++
Linux 专 栏 :Linux

目录
引言:
Linux命令行的功能非常强大,我们用了这么长时间的shell,那么本期我们来自己实现一个简单版的shell。
1. 命令行提示符
我们可以先看一下原本的shell:
要实现一个shell先得有一个命令行提示符,这个命令行提示符前面是用户名,中间是主机号,后面是工作目录,这些属性我们可以直接定义,但是在Linux环境变量中都保存着这些属性,并且是动态的,所以我们直接使用环境变量中的这些属性;
在程序中获取环境变量的接口叫做getenv:
#include <stdlib.h> char *getenv(const char *name);接下来我们先使用getenv实现三个获取命令行提示符的函数:
// 获取用户名 const char* getUsername() { const char* name = getenv("USER"); if(name) return name; return "none"; } // 获取主机名 const char* getHostname() { const char* hostname = getenv("HOSTNAME"); if(hostname) return hostname; return "none"; } // 获取当前工作目录 const char* getCwd() { const char* cwd = getenv("PWD"); if(cwd) return cwd; return "none"; }获取完成之后,紧接着按照原本shell的格式来把他们拼接在一起打印出来看一看:
int main() { // 打印命令行提示符 printf("[%s@%s %s]# ", getUsername(), getHostname(), getCwd()); return 0; }
可以看到我们的shell命令行提示符已经完成了,接下来就需要获取用户输入的命令了。
2. 获取用户指令
要获取用户输入的指令,我们先定义一个用来保存指令的字符数组,由于我们输入的指令可能不只是单纯的一个,还会输入一些带选项的指令,此时就不能使用scanf来读取,需要用按行读取的函数接口,我们选择fgets:
C语言会默认打开三个流:
- ① 标准输入流:stdin
- ② 标准输出流:stdout
- ③ 标准错误流:stderr
所以我们从标准输入流中读取用户写入的命令:
#define NUM 1024 int main() { char usercommand[NUM]; // 打印命令行提示符 printf("[%s@%s %s]# ", getUsername(), getHostname(), getCwd()); // 获取用户输入命令 char* r = fgets(usercommand, sizeof(usercommand), stdin); if(r == NULL) return 1; return 0; }当我们输入命令时,最后肯定会跟上一个'\n',所以我们需要将命令行中的最后一个位置的'\n'设置为'\0'。
int main() { char usercommand[NUM]; // 打印命令行提示符 printf("[%s@%s %s]# ", getUsername(), getHostname(), getCwd()); // 获取用户输入命令 char* r = fgets(usercommand, sizeof(usercommand), stdin); if(r == NULL) return 1; // 命令规范化 usercommand[strlen(usercommand) - 1] = '\0'; // 不会存在越界问题 return 0; }这样写是不存在越界的问题,假设我们什么命令都不输入,但是最后还是会敲一下回车,所以只有一个'\n',将这个'\n'改为'\0'也符合预期。
2.1 封装命令行和获取指令
将打印命令行提示符和获取用户指令封装称为一个函数,后面我们直接调用这个函数即可。
#include <stdio.h> #include <stdlib.h> #define NUM 1024 int getUserCommand(char *command, int sz) { // 打印命令行提示符 printf("[%s@%s %s]# ", getUsername(), getHostname(), getCwd()); // 获取用户输入命令 char* r = fgets(command, sz, stdin); if(r == NULL) return -1; // 命令规范化 command[strlen(command) - 1] = '\0'; // 不会存在越界问题 return strlen(command); } int main() { char usercommand[NUM]; getUserCommand(usercommand, sizeof(usercommand)); //printf("%s", usercommand); return 0; }
3. 执行用户输入的命令
获取完用户输入的指令,接下来就需要执行对应的指令了。
3.1 分割命令字符串
要能正确执行对应的命令,就需要将输入的命令以及选项做合理的分割:分割命令字符串我们选用C语言中的strtok函数:
将分割好的字符串存放在一个字符指针数组中,最后以NULL结尾即可:
<





最低0.47元/天 解锁文章
1837

被折叠的 条评论
为什么被折叠?



