当前位置: 首页 > news >正文

迁安做网站中的cms开发浙江疫情最新情况

迁安做网站中的cms开发,浙江疫情最新情况,神木自适应网站开发,免费做暧暧网站目录 前言: 1 命令行解释器部分 2 获取用户命令行参数 3 命令行参数进行分割 4 执行命令 5 判断命令是否为内建命令 前言: 本文介绍是自主Shell编写,对于shell,即外壳解释程序,我们目前接触到的命令行解释器&am…

目录

前言:

1 命令行解释器部分

2 获取用户命令行参数

3 命令行参数进行分割

4 执行命令

5 判断命令是否为内建命令


前言:

本文介绍是自主Shell编写,对于shell,即外壳解释程序,我们目前接触到的命令行解释器,有bash,还有SSH,对于今天模拟实现的Shell编写,我们模拟的是bash,以及需要的预备知识前文已经介绍了,进程的多方面的知识,在自主Shell编写里面比较重要的是进程程序替换,进程终止,进程等待,进程状态什么的,都是自主Shell编写里面的辅助知识罢了。

那么,话不多说,我们直接进入到Shell编写部分。


1 命令行解释器部分

我们在Centos版本下进行演示,首先,我们平常看到的命令行解释器,呈现的都是这个模样,最开始的_lazy是当前的用户名,@后面的VM-12-14-centos代表的是当前主机名称,后面的~代表的我们所处的当前目录,那么我们这里,就应该要复刻一个一样的出来。

那么第一个问题来了,我们从哪里获取对应的用户名主机名以及目前的目录呢?

此时,前文引进的环境变量,就应该出场了:

输入了env之后,我们可以在环境变量表里面看到许多对应的环境变量,其中HOSTNAME,PWD,USER分别代表的就是主机名称,当前路径,当前用户名。

那么我们如何通过获取?我们已知的是有3种方式,一种是environ,一种是命令行参数表,一种是getenv。

我们这里使用getenv,相对于二级指针environ,getenv是我们最常见的选择,那么我们可以:

   11   char* argv[] = {12   getenv("HOSTNAME"),13   getenv("USER"),14   getenv("PWD")15   };

将获取到的环境变量放在数组argv里面,随即进行打印:

我们直接使用printf打印数组的三个元素,看起来好像没有问题,因为命令行参数是在后面输入,所以我们不能使用\n作为结束,并且,这里介绍一个函数,snprintf,我们不妨使用该函数打印,把所有的环境变量放在一个字符串里面,似乎更好控制一点,这里如果有同学的man手册配置没有齐全的话,可以使用指令:

sudo yum install man-pages

snprintf就是将所有的输出,放到一个字符串里面,此时,我们直接打印该字符即可,所以第一部分的临时代码为:

 34 void OutputBash()  35 {  36   char line[SIZE];  37     38   char* username = GetUser();                                                              39   char* hostname = Gethost();  40   char* cwd = Getcwd();41 42   snprintf(line,sizeof(line),"[%s@%s %s]> ",username,hostname,cwd);43   printf("%s",line);44   fflush(stdout);45 46   // char* argv[] = {47   // getenv("HOSTNAME"),48   // getenv("USER"),49   // getenv("PWD")50   // };51   // char* line;52   // //printf("[%s@%s %s]>",argv[0],argv[1],argv[2]);53   // fflush(stdout);54 }
  8 #define SIZE 5129 10 11 char* GetUser()12 {13   char* user = getenv("USER");14   if(user == NULL) return NULL;15   return user;16 17 }18 19 char* Gethost()                                                    20 {                                                                  21   char* host = getenv("HOSTNAME");                                 22   if(host == NULL) return NULL;                                    23   return host;                                                     24 }                                                                  25                                                                    26 char* Getcwd()                                                     27 {                                                                  28   char* cwd = getenv("PWD");                                       29   if(cwd == NULL) return NULL;                                     30   return cwd;  31   32 }  

但是为什么要说这是临时的呢?因为我们的pwd并不完善:

目前,打印的出来并不是最完善的,较为完善的应该是只打印当前目录。

那么如何保证修饰一下呢?

我们可以将该字符串进行分割,也就是使用指针,将该指针的指向指到最后一个/指向的地方即可。但是这里不推荐使用函数,如果使用的是函数,我们就要使用二级指针,实属麻烦,所以可以使用宏即可:

#define SkipPath(p) do{ p += (strlen(p)-1); while(*p != '/') p--; }while(0)

那么判断的条件就是,只要p碰到了根目录就停下,但是有个缺陷就是:

/还是存在,那么我们可以这样操作:

 snprintf(line,sizeof(line),"[%s@%s %s]> ",username,hostname,strlen(cwd) == 1 ? "/" : cwd + 1); 

此时,较为完善的命令行解释器部分就打印出来了:


2 获取用户命令行参数

第一个问题我们解决了,我们现在该获取用户的命令行参数了。

在获取用户命令行参数这里,我们要注意的点是,我们应该使用什么函数来获取?

可不可以使用scanf来获取呢?如果使用scanf,那么ls -l -n -a,能获取到多少呢?

我们知道scanf是通过空格或者换行符来获取的,此时ls -l -n -a,就只能获取到ls,所以我们应该换个函数,这里推荐fgets,其实gets也是可以的,但是因为后面有文件的IO操作,所以我们使用fgets作为一个缓冲:

 57 int GetUserCommand(char* usercommand,size_t n)  58 {  59   char* s = fgets(usercommand,n,stdin);  60   if(s == NULL) return -1;  61   62   return strlen(s);  63 }  

但是该代码存在一定的缺陷。

在第4部分会有提示。


3 命令行参数进行分割

获取到了对应的命令,那么执行的时候,不能带空格去执行吧?所以我们要使用函数,将命令行参数进行分割,这里使用的函数是C语言的库函数,strtok,相信许多同学已经忘记了,不急:

第一个参数是分割的字符串,第二个参数是分割符,那么第一次分割之后,将第一个参数置为NULL,就会继续分割,我们要做的,就是将字符串分割之后,放到数组里面,有益于后面的进程替换工作。

这里定义一个全局变量,用于存在分割后的字符串变量:

#define SEP " "   char* gArgv[SIZE];

这里有一个非常细小的地方,如果我们使用单引号的空格,虽然也是空格,但是和strtok就不匹配了,因为这并不是cosnt char* ,这只是一个字符而已。

 70 void SplitCommand(char* usercommand)71 {72   gArgv[0] = strtok(usercommand,SEP);73   int index = 1;74   while((gArgv[index++] = strtok(NULL,SEP)));//分割之后函数返回NULL 恰好作为结尾75 76 }

此时有个很不错的代码细节,因为函数分割完返回的就是NULL,刚好可以作为数组的结束标志。


4 执行命令

到现在,我们可以不管三七二十一,直接执行命令了,至少我们现在先不用管命令是不是内建命令,我们就执行几个简单的即可。

那么要执行命令,我们肯定涉及到进程程序替换。因为分割好的命令我们已经放在了全局变量里面,所以我们可以直接创建函数了:

 85 void ExcuteCommand()86 {87   pid_t id = fork();88 89   if(id < 0) Die();90   else if(id == 0)91   {92     //child93     execvp(gArgv[0],gArgv);94     exit(1);95   }96   else 97   {98     //father99     int status = 0;
100     pid_t rid = waitpid(id,&status,0);
101     if(rid > 0)
102     {
103       lastcode = WEXITSTATUS(status);
104       if(lastcode != 0) printf("%s:%s:%d\n", gArgv[0], strerror(lastcode), lastcode);
105     }
106   }
107 
108 
109 }

这些代码都是进程替换的时候介绍过的了,无非是加修饰,让代码更加美观,此时,咱们就可以跑了,但是有同学仍会发现,不管怎么运行,都是不可以的,因为我们命令行输入的时候,都会自动的输入一个回车,这个回车,导致了我们跑不了,所以我们需要将回车干掉:

宏定义ZERO即可。

此时,我们就可以正常的执行了。


5 判断命令是否为内建命令

那么现在问题来了,如果我们是执行的ehco,cd这种内建命令,即只能父进程来执行的,我们就不能创建子进程了,判断是否为内建命令,条件成立就内建执行即可,并且跳过下一步:

那么判断内建命令的方式也是十分简单粗暴的,strcmp即可:

110 void Cd()
111 {
112     const char *path = gArgv[1];
113     if(path == NULL) path = Gethost();
114     // path 一定存在
115     chdir(path);
116 
117     // 刷新环境变量
118     char temp[SIZE*2];
119     getcwd(temp, sizeof(temp));
120     snprintf(cwd, sizeof(cwd), "PWD=%s", temp);
121     putenv(cwd); // OK
122 }
123 
124 int IsInorder()
125 {
126     int yes = 0;
127     const char *enter_cmd = gArgv[0];
128     if(strcmp(enter_cmd, "cd") == 0)
129     {
130         yes = 1;
131         Cd();
132     }
133     else if(strcmp(enter_cmd, "echo") == 0 && strcmp(gArgv[1], "$?") == 0)  
134     {  
135         yes = 1;  
136         printf("%d\n", lastcode);  
137         lastcode = 0;                                                                              
138     }  
139     return yes;  
140 }

这里拿cd举例子,判断cd是内建命令之后,在cd函数实现,因为我们要该目录,所以使用函数chdir,改变当前工作目录,改变了之后,改变环境变量中的PATH即可。此时自主shell编写就差不多了。


感谢阅读!

http://www.dinnco.com/news/8989.html

相关文章:

  • 乌鲁木齐做网站公司seo运营培训
  • 门户网站建设方案 模板微信搜一搜怎么做推广
  • 网页特效代码免费网站网站制作的流程是什么
  • div做网站网站提交百度收录
  • 我做彩票网站开发彩票网站搭建深圳网络seo推广
  • 网站设置快捷方式到桌面做一套二级域名网站怎么做
  • 商城网站建设行情苏州网站外包
  • 智能网站价格百度云盘登录电脑版
  • 游戏网站建设与策划国外免费网站域名服务器查询
  • 网页设计茶叶网站建设seo岗位有哪些
  • 立即关注公众号宁波seo排名优化培训
  • 优秀品牌企业网站建设案例盘多多百度网盘搜索引擎
  • 做网站最低多少钱今日小说搜索风云榜
  • php动态网站教程怎么看关键词的搜索量
  • 南汇做网站广州竞价外包
  • 西安做网站那家公司好河北seo基础
  • 徐州做汽车销售的公司网站谷歌seo网站优化
  • 网站建设与功能模块怎样才能在百度上发布信息
  • 网站备案提示怎么创建网址
  • 嘉兴市建设监理协会网站软服业营收破334亿
  • 上海哪个网站最好用广州网站推广
  • 大连商城网站建设地推接单平台网
  • 做网站大作业的心得体会电子商务网站建设多少钱
  • qq钓鱼网站生成器手机版安徽网络建站
  • 发布做任务网站app广告联盟
  • 惠阳网站设计开发优化大师下载旧版本安装
  • 高端设计参考网站网站查询平台
  • 有趣的网站初音社会化媒体营销
  • 国内网站设计欣赏活动策划
  • 建设局网站查询个人信息关键词优化推广公司哪家好