1.原理
1)打印提示符
格式:[用户名@主机名 当前目录]提示符
例如:[mou@VM-0-7-centos Linux_Lesson]$
相关接口:
获取当前用户名:char *getlogin(void);
获取主机名:int gethostname(char* hostname,size_t len);
获取当前工作路径:char* getcwd(char* buf,size_t len);
2)用户输入命令
使用字符串接受用户收入的命令,注意用户输入命令和选项的处理。
例如:输入ls -l可能只能接收到ls
处理方法:使用c++中string的getline方法进行输入
3)解析命令
将命令和选项分离,注意用户输入时可能存在选项之间存在多个空格的情况。将命令解析到args数组中,args[0]具体命令,其他位选项;
4)创建子进程执行命令
使用fork创建子进程,并且在子进程中使用execvp进行进程替换。
5)父进程等待子进程退出
在父进程中使用wait进行等待。
2.源程序
#include<iostream>
#include<string>
#include<sys/wait.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<unistd.h>
#include<netdb.h>
using namespace std;
int main()
{
while(1)
{
//获取当前用户名
char *name = getlogin();
//获取当前主机名
char hostname[20];//主机名
gethostname(hostname,17);
//获取当前工作目录
char buf[256];
getcwd(buf,128);
//提取当前工作路径的最后一层
char* buffer = NULL;
for(int i = 255;i >= 0;i--)
{
if(buf[i] == '/')
{
buffer = &buf[i+1];
break;
}
}
//打印提示符
printf("[%s@%s %s-myshell]$ ",name,hostname,buffer);
//用户输入命令
string cmd;
getline(cin,cmd);
char* cmd1;
strcpy(cmd1,cmd.c_str());
//解析命令
char* args[256];
string ch = " ";
args[0] = strtok(cmd1,ch.c_str());
for(int i = 1;i < 256;i++)
{
args[i] = strtok (NULL, ch.c_str());
if(args[i] == NULL)
break;
}
//创建子进程执行命令
pid_t id = fork();
if(id < 0)
{
//error
cout<<"error"<<endl;
exit(-1);
}
else if(id == 0)
{
//子进程,进行程序替换,执行指令
execvp(args[0],args);
exit(0);
}
else
{
//父进程,等待子进程退出
wait(NULL);
}
}
return 0;
}
注:为了和xshell提示符区别开,这里提示符后边加了-myshell
3.运行结果演示