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.父进程等待子进程退出

相关推荐
tanyongxi664 分钟前
Linux 中 Git 使用指南:从零开始掌握版本控制
linux·git
攻城狮7号5 分钟前
【第九节】windows sdk编程:通用控件的使用
c++·windows·windows编程·windows sdk
UpUpUp……14 分钟前
Linux中Gdb调试工具常用指令大全
linux·运维·服务器·笔记
曦月逸霜36 分钟前
第十次CCF-CSP认证(含C++源码)
数据结构·c++·算法·ccf-csp
若云止水1 小时前
ngx_conf_read_token
linux·运维·服务器
重生之我在20年代敲代码1 小时前
Linux工具【1】(编辑器vim、编译器gcc与g++)
linux·服务器·编辑器
眠りたいです1 小时前
Linux:利用System V系列的-共享内存,消息队列实现进程间通信
linux·运维·服务器·c++·进程间通信
moz与京1 小时前
【附JS、Python、C++题解】Leetcode面试150题(9)——三数之和
javascript·c++·leetcode
nqqcat~1 小时前
函数的引用/函数的默认参数/函数的占位参数/函数重载
开发语言·c++·算法
pp-周子晗(努力赶上课程进度版)2 小时前
《从零手写Linux Shell:详解进程控制、环境变量与内建命令实现 --- 还会更新》
linux·运维·服务器