一、前言
本文利用进程相关知识,实现一个简易版的 SHELL。
二、SHELL 实现
1.获取命令行,实现交互
实现 SHELL 的第一步是从键盘获取用户的输入,即命令行。
设置打印格式
#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
int quit = 0;
char commandline[LINE_SIZE];
char pwd[LINE_SIZE];
// 获取用户名
const char *getusername() {
return getenv("USER");
}
// 获取主机名
const char *gethostname() {
return getenv("HOSTNAME");
}
// 获取当前进程所处路径
void getpwd() {
getcwd(pwd, sizeof(pwd));
}
// 设置打印格式
printf(LEFT "%s@%s %s" RIGHT "" LABLE " ", getusername(), gethostname(), pwd);
获取键盘输入
在获取键盘输入的函数有很多,这里以 fgets() 函数为例。我们需要定义一个字符数组来存储读取的命令行参数。注意细节:读到字符串的 \n 需换成 \0,因为 fgets 默认以换行作为分隔符,读到的字符串会包括换行符,但这并非命令输入的一部分。
#define LINE_SIZE 1024
char commandline[LINE_SIZE];
void interact(char* cline, int size) {
getpwd();
printf(LEFT "%s@%s %s" RIGHT "" LABLE " ", getusername(), gethostname(), pwd);
char *s = fgets(cline, size, stdin);
assert(s);
(void)s;
cline[strlen(cline)-1] = '\0';
}
至此完成了命令行参数的获取。由于 SHELL 进程一直读取用户输入,因此设置为循环形式。
int quit = 0;
void interact(char* cline, int size) {
getpwd();
printf(LEFT "%s@%s %s" RIGHT "" LABLE " ", getusername(), gethostname(), pwd);
char *s = fgets(cline, size, stdin);
assert(s);
(void)s;
cline[strlen(cline)-1] = '\0';
if(s) printf("echo : %s\n", cline);
}
int main() {
while(!quit) {
// 1. 交互问题,获取命令行
interact(commandline, sizeof(commandline));
}
return 0;
}
运行后可验证格式和读取是否正确。

