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

做淘宝要用的网站手游网站源码下载

做淘宝要用的网站,手游网站源码下载,网络营销策划书 范例,网站开发一般包括目录 思路 创建自己的命令行 获取用户命令 分割命令 检查是否是内建命令 cd命令实现 进程程序替换执行程序 总代码 结语 思路 int main() {while (1){// 1. 自己的命令行PrintCommandLine();// 2. 获取用户命令char command[SIZE];int n GetUserCommand(command, si…

目录

思路

创建自己的命令行

获取用户命令

分割命令

检查是否是内建命令

cd命令实现

进程程序替换执行程序

总代码

结语


思路

int main()
{while (1){// 1. 自己的命令行PrintCommandLine();// 2. 获取用户命令char command[SIZE];int n = GetUserCommand(command, sizeof(command));if (n <= 0)return 1;// 3. 分割指令SplitCommand(command);// for(int i = 0; gArgv[i]; i++)//     printf("[%d]: %s\n", i, gArgv[i]);// 4. 检查是否是内建命令n = CheckBuildin();if(n) continue;// 5. 进程程序替换执行命令ExecuteCommand();}return 0;
}

上图中的五个函数,就是我们的思路

首先就是先写命令行:

就是这个,这个获取环境变量 + 指针操作 + 打印即可,较为简单

接着就是需要获取用户输入的指令,并且将其分割,放进数组里面,这里会涉及到strtok函数的使用

最后将我们的函数分割完之后,就是判断是否是内建命令了

如果是内建命令的话,这里就只实现cd和echo $?,我们就单独函数实现

如果不是内建命令的话,我们就正常进行程序替换即可

这里最关键的点就是程序替换了,因为我们要使用的所有的命令都在磁盘上保存着,这时我们fork创建子进程,并用程序替换将磁盘上待替换的程序加载到内存中并将这个子进程给覆盖,最终跑起来

创建自己的命令行

#define SkipPath(p)         \do                      \{                       \p += strlen(p) - 1; \while (*p != '/')   \p--;            \} while (0)const char *GetHome()
{const char *home = getenv("HOME");return home;
}const char *GetHostName()
{const char *hostname = getenv("HOSTNAME");return hostname;
}const char *GetCwd()
{const char *cwd = getenv("PWD");return cwd;
}const char *GetUserName()
{const char *name = getenv("USER");return name;
}void PrintCommandLine()
{char line[SIZE];const char *UserName = GetUserName();const char *Cwd = GetCwd();const char *HostName = GetHostName();SkipPath(Cwd);snprintf(line, sizeof line, "[%s@%s %s]:>", UserName, HostName, strlen(Cwd) == 1 ? "/" : Cwd + 1);printf("%s", line);fflush(stdout);
}

这里没什么好说的,主要就是getenv获取环境变量,我们的参数就是从环境变量中来

需要讲的一点就是do...while(0)那个宏,这里我们如果直接获取PWD的话,就是所有都打出来:

这个是效果

但是整体是这样的

所以我们需要将指针移动到最后面那里,然后只显示最后一段

但是这里为什么用的是宏呢?因为这里是用 c 语言实现的,写一个函数的话还要二级指针,太麻烦了,宏方便点

而使用do...while(0)是为了形成一个代码块,我们可以整体使用,并且在下面调用的时候可以随便加 “ ; ”,这样调用起来就和函数一样了

最终效果如下:

获取用户命令

int GetUserCommand(char command[], size_t n)
{char *s = fgets(command, n, stdin);if (s == NULL)return 2;// 处理 \ncommand[strlen(command) - 1] = ZERO;// printf("命令: %s", command);return strlen(command);
}

其实如果是cpp的话,就直接getline了,但是c语言实现的话我们就用 fgets 获取一行

直接获取即可,完了之后放进提前开辟并传进函数里面的数组中

需要说的一点就是,我们用户输入的指令看起来是这样的:

ls -a -l

但其实最后还会加一个回车表示确定,所以实际上就是这样子的:

ls -a -l\n

综上,我们就需要将最后一个位置设置为\0,上面的ZERO其实就是\0,只不过设置成了宏而已

分割命令

void SplitCommand(char *command)
{gArgv[0] = strtok(command, SEP);int index = 1;while (gArgv[index++] = strtok(NULL, SEP));// 在最后一次判断的时候,发现没有字符串了,strtok 就会返回NULL// 正好让 gArgv 的最后一个位置变为 NULL,这样在后面进程程序替换的时候就可以直接用
}

这里其实就是strtok函数的使用技巧

先说说为什么要分割:

我们获取了程序之后,不是说所有的功能都是我们自己写,像ls、cd、mkdir等等,这些指令在我们电脑中的磁盘上人家都帮我们写好了,shell也是调用的这些文件

所以我们要做的,就是在用户输入指令的时候,我们能将这些程序加载进来

这里就需要用到进程程序替换了,并且我们现在只有用户输入的数据,我们到后面肯定是execvp用起来最好,所以分割完直接放函数里面当参数即可,就实现这个功能了

再来说说 strtok

当你第一次使用strtok的时候,传入一个数组当参数(第一个参数位置,第二个是分隔符)

当你从第二次开始,第一个参数直接传NULL,就代表使用你一刚开始用个的那个数组

这也就是为什么一开始传command数组,后面传NULL的原因

接着最妙的就是,当strtok检测到没有可以分割的了,就会返回NULL,而我们的数组(execvp函数要求)最后一个位置必须以NULL结尾

检查是否是内建命令

int CheckBuildin()
{int yes = 0;const char *enter_cmd = gArgv[0];if(strcmp(enter_cmd, "cd") == 0){yes = 1;Cd();}else if(strcmp(enter_cmd, "echo") == 0 && strcmp(gArgv[1], "$?") == 0){yes = 1;printf("%d\n", lastcode);lastcode = 0;}return yes;
}

直接就是if、else检查判断就行,有多少个内建命令就有多少个if、else

cd命令实现

void Cd()
{const char* path = gArgv[1];if(path == NULL) path = GetHome();chdir(path);// 更新环境变量char cwd[SIZE];char temp[SIZE];getcwd(temp, sizeof temp);snprintf(cwd, sizeof(cwd), "PWD=%s", temp);setenv("PWD", cwd, 1);
}

这里主要用到的是chdir函数,ps:chdir支持直接使用 . 或者 ..

先说获取path,程序走到这里,那么用户输入的指令一定是cd,那么就会有像cd ..这样的指令

那么我们获取完之后,分割的指令中,第二个就一定是path,直接获取就好(下标是1)

当然也有可能用户直接输入一个cd,后面啥也不跟,我们随便处理一下,给他返回到家目录即可

最后我们在chdir之后,还需要更新一下路径

这里我们先获取环境变量中的PWD,然后使用snprintf写入数组中,以PWD:%s的格式

最后直接用setenv函数修改(或者说更新)环境变量即可

当然你也可以在最后使用putenv,这样的话,我们的cwd数组就需要开辟在全局,不然函数运行结束之后,cwd数组也就没了,这样putenv找不到他,就会直接异常终止我们的程序,显示段错误(Segmentation fault)

setenv就不用,这里推荐这个,因为他更现代、好用

进程程序替换执行程序

void ExecuteCommand()
{pid_t id = fork();if (id == 0){// 子进程execvp(gArgv[0], gArgv);exit(errno);}else{// 父进程int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){if(WIFEXITED(status) == 0){lastcode = WEXITSTATUS(status);printf("exit code: %d, exit signal:%d\n", WEXITSTATUS(status), WTERMSIG(status));}}}
}

就是execvp函数的使用,创建子进程直接替换,然后父进程在外面waitpid阻塞等待即可,也不用父进程干什么事情

总代码

MyShell.c

点开这个链接,里面就是代码,放在gitee里面了

结语

这篇文章到这里就结束啦!!~( ̄▽ ̄)~*

如果觉得对你有帮助的,可以多多关注一下喔

http://www.dtcms.com/a/541912.html

相关文章:

  • Mysql基础知识之SQL语句——库表管理操作
  • 类似于建设通的网站巴中做网站 微信开发
  • dede装修网站模板预付网站建设服务费如何入账
  • Python异常处理详解:从概念到实战,让程序优雅应对错误
  • 长沙做网站推荐网站显示iis7
  • elasticSearch之API:索引操作
  • 网站建设官网怎么收费哪个网站可以做竖屏
  • 苏州做网站哪家比较好移动端快速排名
  • 做淘宝网站要多少钱如何申请域名邮箱
  • dede网站地图文章变量网站开发课程心得
  • 网站模板绑定域名中国交通建设集团有限公司英文名
  • BeautifulSoup 的页面中需要获取某个元素的 xpath 路径
  • 网站数字证书怎么做辽宁省建设工程注册中心网站
  • 网站开发 总结报告网站的版面设计
  • 网站策划素材网站备份流程
  • 最成功的个人网站新民电子网站建设哪家好
  • 十堰网站搜索优化价格网站建设流程新闻
  • 厦门网站制作公司创网网站后台管理系统
  • 汕头网站制作推荐小程序制作报价
  • 网站建设工作室 杭州网站建设方案论文1500
  • 6.1类的继承
  • 广东集团网站建设安徽网络seo
  • 爱站查询个人如何学习做网站
  • 怎么开发一个网站安徽省建筑工程信息平台
  • 石家庄网络建站中粮我买网是哪个公司做的网站
  • vue2弹出框组件demo
  • G-Star Landscape 3.0 更新,网页版同步上线!
  • 让进程永不掉线:Linux nohup命令的深度指南
  • 虚拟机上部署Web项目
  • 做类似淘宝的网站需多少资金销售类wordpress