myshell

cpp 复制代码
  1 #include<cstdio>                                                                                                          
  2 #include<string.h>
  3 #include<string>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<cstdbool>
  7 #include<sys/types.h>
  8 #include<sys/wait.h>
  9 #include<unistd.h>
 10 #include<iostream>
 11 #define command_size 1024
 12 #define format "[%s@%s %s]#"
 13 //下面定义shell的全局变量 
 14 char cwd[1024];
 15 char cwdenv[1024];
 16 using namespace std;
 17 #define maxargc 128
 18 char*  my_argv[maxargc];
 19 #define maxenv 2000
 20 char* my_env[maxenv];
 21 int lastcode=0;
 22 int argc=0;
 23 int myenvs=0;
 24 const char* getusername()
 25 {
 26     const char* name=getenv("USER");
 27     return name==NULL?"None":name;
 28 }
 29 const char* gethostname()
 30 {
 31     const char* hostname=getenv("HOSTNAME");
 32     return hostname==NULL?"None":hostname;
 33 }
 34 const char* getpath()
 35 {
 36     const char* path=getcwd(cwd,sizeof(cwd));//获得当前进程的工作路径
 37     if(path)
 38     {
 39         snprintf(cwdenv,sizeof(cwdenv),"PWD=%s",cwd);
 40         putenv(cwdenv);
 41     }
 42     return path==NULL?"None":path;
 43 }
 44 const char* gethome()
 45 {
 46     const char* home=getenv("HOME");
 47     return home==NULL?NULL:home;
 48 }
 49 void makecmdline(char cmd_prompt[],int size)
 50 {
 51     snprintf(cmd_prompt,size,format,getusername(),gethostname(),getpath());                                               
 52 }
 53 void printcmdprompt()
 54 {
 55     char prompt[command_size];
 56     makecmdline(prompt,sizeof(prompt));
 57     printf("%s ",prompt);
 58     fflush(stdout);
 59 }
 60 bool getcommandline(char* out,int size)
 61 {    
 62     char* c=fgets(out,size,stdin);
 63     if(c==NULL) return false;
 64     out[strlen(out)-1]=0;
 65     if(sizeof(out)==0) return false;
 66     return true;
 67 }
 68 #define dsp " "
 69 bool commandparse(char* commandline)
 70 {
 71     argc=0;
 72     my_argv[argc++]=strtok(commandline,dsp); 
 73     while((bool)(my_argv[argc++]=strtok(NULL,dsp)));
 74     argc--;
 75     return argc>0?true:false;
 76 }
 77 int execute()
 78 {
 79     pid_t id=fork();
 80     int status=0;
 81     if(id==0)
 82     {
 83         //子进程
 84         execvp(my_argv[0],my_argv);                                                                                       
 85         exit(1);
 86     }
 87     pid_t rid=waitpid(id,&status,0);
 88     if(rid>0)
 89     {
 90         lastcode=WEXITSTATUS(status);
 91         
 92     }
 93     return 0;
 94 }
 95 bool check()//查看是否是内建命令,并对内建命令进行相应的操作
 96 {
 97     string cmd=my_argv[0];
 98     if(cmd=="cd") {
 99         if(argc==1)//返回家目录
100         {
101             if(gethome()==NULL) return true;
102             else chdir(gethome());
103         }
104         else{
105             string where=my_argv[1];
106             chdir(where.c_str());
107         }
108         return true;                                                                                                      
109     }
110     else if(cmd=="echo")
111     {
112         if(argc==2)
113         {
114             //echo "hello wworld"
115             //echo $?
116             //echo $PATH
117             string opt=my_argv[1];
118             if(opt=="$?") 
119             {
120                 cout<<lastcode<<endl;
121                 lastcode=0;
122             }
123             else if(opt[0]=='$')//查找父进程的环境变量,因为我们今天并没有创建自己进程的环境变量表,所以我们还是使用从父进    程继承的环境变量
124             {
125                 string envname=opt.substr(1);
126                 if(getenv(envname.c_str())) cout<<getenv(envname.c_str())<<endl;
127             }
128             else 
129             {                                                                                                             
130                 cout<<opt<<endl;
131             }
132         }
133         return true;
134     }  
135     else if(cmd=="export")
136     {
137         if(argc==2)
138         {
139             my_env[myenvs]=(char*)malloc(strlen(my_argv[1])+1);
140             strcpy(my_env[myenvs++],my_argv[1]);//strcpy会拷贝字符串结尾的\0,但是strlen并不会将\0计算在内
141             putenv(my_env[myenvs-1]);
142         }     
143         return true;
144     }
145     else return false;
146 }
147 void initenv()
148 {
149     extern char** environ;
150     memset(my_env,0,sizeof(my_env));
151     myenvs=0;
152     for(int i=0;environ[i];i++)
153     {
154         my_env[i]=(char*)malloc(strlen(environ[i])+1);
155         strcpy(my_env[i],environ[i]);
156         myenvs++;                                                                                                         
157     }
158     my_env[myenvs++]=(char*)"test=haha";
159     my_env[myenvs]=NULL;
160 
161     //导成环境变量
162     for(int i=0;my_env[i];i++)
163     {
164         putenv(my_env[i]);//换将变量中如果没有这个环境变量名字就新增这个环境变量,否则就将其替换。
165     }
166 }
167 int main()
168 {
169     //shell启动的时候要从系统中获取环境变量
170     //我们的环境变量的信息应该来原来父进程
171     initenv();
172     while(1)
173     {
174         //输出命令行提示符
175         printcmdprompt();
176         //获取用户输入的命令
177         char commandline[command_size];
178         if(!getcommandline(commandline,sizeof(commandline)))
179             continue;
180         //命令行分析
181         if(!commandparse(commandline)) continue;
182         //检查是否是内建命令
183         if(check()) continue;
184         //执行命令
185         execute();
186     }
187     return 0;
188 }   

命令行解释器:

1.获取命令行

2.解析命令行

3.建立子进程

4.替换子进程

5.父进程等待子进程退出

相关推荐
c-c-developer3 分钟前
C++ Primer 标准库类型string
开发语言·c++
宁静致远202127 分钟前
Ubuntu下的Doxygen+VScode实现C/C++接口文档自动生成
c++·vscode·ubuntu
Bluesonli32 分钟前
第 2 天:创建你的第一个 UE5 C++ 项目!
c++·学习·ue5·虚幻·虚幻引擎·unreal engine
比特在路上1 小时前
蓝桥杯之c++入门(四)【循环】
c++·职场和发展·蓝桥杯
pay顿1 小时前
C++基础day1
c++·学习·笔试
孤寂码农_defector1 小时前
C++【iostream】数据库的部分函数功能介绍
c++
Icomi_2 小时前
【PyTorch】7.自动微分模块:开启神经网络 “进化之门” 的魔法钥匙
c语言·c++·人工智能·pytorch·python·机器学习·计算机视觉
余辉zmh2 小时前
【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(二)
c++·算法·leetcode·贪心算法
余辉zmh2 小时前
【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(一)
c++·算法·leetcode·贪心算法
taoyong0012 小时前
代码随想录算法训练营第三十七天-动态规划-完全背包-377. 组合总和 Ⅳ
c++·算法·leetcode·动态规划