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

做翻译的网站网站开发硬件环境怎么填

做翻译的网站,网站开发硬件环境怎么填,wordpress编辑器不能用,广东企业移动网站建设哪家好Linux 自主 shell 编写#xff08;C 语言实现#xff09; 效果主要步骤打印命令行提示符获取用户命令字符串切割用户命令字符串执行命令循环 至此源码#xff08;简易半成品#xff09;细节内建命令问题cd 退出码问题echo 查看退出码 完整源码makefilemyshell.c 效果 效果… Linux 自主 shell 编写C 语言实现 效果主要步骤打印命令行提示符获取用户命令字符串切割用户命令字符串执行命令循环 至此源码简易半成品细节内建命令问题cd 退出码问题echo 查看退出码 完整源码makefilemyshell.c 效果 效果嘛和 命令行解释器 一模一样这里就不贴图了 只是把 # 超管 或 $ 普通用户 符号改为 以作区分 注意哦 删除键不能直接使用要配合 ctrl 键才行 主要步骤 打印命令行提示符 在 Linux 终端命令行里首先看到的是 命令行提示符 [exerciselocalhost my_shell]$ 此 shell 一旦跑起来定是要先打印 命令行提示符 的但是这玩意对于不同的用户是不一样的呀所以不能单纯的打印出来而是要获取用户名主机名等等如何获取目前来说对各种 系统接口还不熟那就直接使用 环境变量 嘛 命令行执行 env 命令就可以看到很多 环境变量 ^ ^ 但 系统环境变量 很多不容易直接得到想要的所以可以使用库函数 getenv 来获取需要包含头文件 #include stdlib.h 函数原型如下 char *getenv(const char *name);那么 用户名、 主机名 和 工作目录 分别在 USER 、HOSTNAME 和 PWD 内直接使用 getenv 函数获取即可 最后使用 snprintf() 函数拼接成 命令行提示符 的格式即可函数原型 int snprintf(char *str, size_t size, const char *format, ...);获取用户命令字符串 C 语言 获取键盘字符串 可以使用库函数 scanf() 但它遇到空格可就不继续读取了而它的高端玩法还不熟 咱就老老实实使用 fgets 函数原型 char *fgets(char *s, int size, FILE *stream);切割用户命令字符串 这一步是必要的因为日后一定是需要 进程替换 的进程替换 就一定需要将用户命令以空格为分隔符打散分开是库函数参数的原因是刚需 如何实现呢倒是也很简单我们可以直接将空格替换为 \0 那么一个长串就变为若干个子串 如果要执行用户输入的命令是要创建子进程来完成的那我们就需要为进程传递 命令行参数 来实现毕竟不同的选项具有不同的功能所以切割的字串分别放入 命令行参数表 argv[] 里即可argv 的每一个元素都是一个指针指向被切完成的子串最后一个指针为 NULL 那么只需要将 argv 的第一个元素指向第一个子串第二个元素指向第二个子串以此类推 但这比较麻烦咱可以使用库函数 strtok() 完成 命令行参数表 也可以设置为全局的好调用 执行命令 获取用户的命令后不执行等啥呢 当然啦执行命令不是自己当前进程来执行而是 创建子进程在利用 进程替换此时子进程就可以执行你想要的全新的代码 循环 一个 shell 怎么能只运行一条命令呢所以我们需要将上述过程循环起来这样就能无限制运行命令 至此简易到不能再简易的 shell 就实现好了 至此源码简易半成品 #include stdio.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/wait.h #include string.h #include errno.h#define SIZE 512 #define ZERO \0 #define SEP #define NUM 32char* gArgv[NUM];const char* getUserName() {const char* username getenv(USER);if (username NULL) return None;return username; }const char* getHostName() {const char* hostname getenv(HOSTNAME);if (hostname NULL) return None;return hostname; }// 临时 const char* getCwd() {const char* cwd getenv(PWD);if (cwd NULL) return None;return cwd; }void MakeCommandLineAndPrint() {char line[SIZE];const char* username getUserName();const char* hostname getHostName();const char* cwd getCwd();snprintf(line, sizeof(line), [%s%s %s] , username, hostname, cwd);printf(%s, line);fflush(stdout); }int GetUserCommand(char command[], size_t size) {char* s fgets(command, size, stdin);if (s NULL) return -1;command[strlen(command) - 1] ZERO;return strlen(command); }void SplitCommand(char command[], int size) {gArgv[0] strtok(command, SEP);int index 1;while ((gArgv[index] strtok(NULL, SEP)));}void Die() {exit(1); }void ExecuteCommmand() {pid_t id fork();if (id 0) Die();else if (id 0){// childexecvp(gArgv[0], gArgv);exit(errno);}else {// parentint status 0;pid_t rid waitpid(id, status, 0);if (rid 0){}} }int main() {int quit 0;while (!quit){// 自己需要输出一个命令行MakeCommandLineAndPrint();// 获取用户命令字符串char usercommand[SIZE];int num GetUserCommand(usercommand, sizeof(usercommand));if (num 0) return 1;// 分割用户命令字符串SplitCommand(usercommand, sizeof(usercommand));// 执行命令ExecuteCommmand();}return 0; }细节 上面的代码虽然说可以运行但有很多漏洞和细节尚未修补实现接下来一一填补 内建命令问题 cd 举个例子吧上面的代码先跑起来不说其他的试试 cd 命令能不能正常运行 不能正常运行 这个的漏洞不是一般的大并不是不能使用 cd 命令而是命令 cd 对咱这个 shell 不起任何作用 而如果你们运行上面的残本代码会发现当前的工作路径是一串绝对路径要想切割最后一个目录拿过来倒也容易但 cd 还是无法生效啊 为什么 其实很简单我们是实现 shell 的方法是 创建子进程然后拿想要的进程去替换这个子进程由于进程的独立性子进程会影响父进程吗肯定不会那子进程执行 cd 命令和你父进程有什么关系呢子进程执行 cd 命令的时候父进程在干嘛在那 wait 呢 所以这样实现父进程 shell 的工作路径改不了的那如何能改当然是父进程自己执行咯 所以像 cd 这样的命令是 内建命令 既如此观察上述代码在执行命令之前 需要检查是否有 内建命令 如何检查 直接判断不就行了它有几个 内建命令咱就判断几次如果用户输入的是 cd 命令shell 就自己执行 如何执行这种涉及系统的东西当然要 系统调用 嘛chdir 可以将当前进程的工作路径切换至你想要的路径那咱们就可以直接 将用户输入的路径 传进 chdir 的参数里即可 注意如果直接运行 cd 命令是返回用户家目录的所以如果切割后的子串只有 cd 第二个元素路径为 NULL 的话可直接返回 用户家目录可函数实现 改完之后记得要修改 shell 下一次打印出来的命令行路径因为这是被我封装为函数的直接修改较为麻烦但我是从环境变量里获取的所以直接修改环境变量即可 首先使用函数 getcwd 此函数可以直接获取真正的工作路径然后拼接 PWD 再使用函数 putenv() 来刷新环境变量 // 内建命令 cd 的执行过程 void Cd() {// 获取 cd 路径const char* path gArgv[1];if (path NULL) path getHome();// 此时 path 一定存在那么可以直接使用 系统调用 修改工作路径chdir(path);// 获取此时的工作路径char temp[SIZE * 2];getcwd(temp, sizeof(temp));// 拼接 PWD 环境变量snprintf(Cwd, sizeof(Cwd), PWD%s, temp);// 刷新环境变量putenv(Cwd); }// 检查是否有内建命令 int CheckBuildIn() {int yes 0;const char* enter_cmd gArgv[0];if (strcmp(enter_cmd, cd) 0){yes 1;Cd();}// 继续判断其他内建命令...return yes; } 至此最大的坑已经被补上了至于命令行解释器里当前工作目录的切割使用宏函数可直接实现后附完整源码这里不做解释 // 宏函数 #define SkipPath(pCwd) do { pCwd (strlen(pCwd) - 1); while (*pCwd ! /) --pCwd; } while (0)退出码问题 父进程是一定要得到子进程的退出码的不然有问题无法准确反馈给用户 具体实现也是进程替换的内容非常简单看源码 echo 查看退出码 当然是下面这个命令啦 echo $?和上面 cd 命令一样需要在 CheckBuildIn 函数里进行判断是否有 echo $? 命令逻辑编写十分简单在 CheckBuildIn 函数里编写即可 else if (strcmp(enter_cmd, echo) 0 strcmp(gArgv[1], $?) 0) {yes 1;printf(%d\n, lastcode);lastcode 0; }完整源码 CentOS 7.9 平台 gcc 编译测试进入 可执行文件 MyShell 所在目录下 ./MyShell 即可运行 makefile binMyShell srcmyshell.c$(bin):$(src)gcc $^ -o $ .PHONY:clean clean:rm -f $(bin)myshell.c #include stdio.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/wait.h #include string.h #include errno.h#define SIZE 512 #define ZERO \0 #define SEP #define NUM 32 #define SkipPath(pCwd) do { pCwd (strlen(pCwd) - 1); while (*pCwd ! /) --pCwd; } while (0)char* gArgv[NUM]; char Cwd[SIZE]; int lastcode 0;const char* getHome() {const char* home getenv(HOME);if (home NULL) return /;return home; }const char* getUserName() {const char* username getenv(USER);if (username NULL) return None;return username; }const char* getHostName() {const char* hostname getenv(HOSTNAME);if (hostname NULL) return None;return hostname; }// 临时 const char* getCwd() {const char* cwd getenv(PWD);if (cwd NULL) return None;return cwd; }void MakeCommandLineAndPrint() {char line[SIZE];const char* username getUserName();const char* hostname getHostName();const char* cwd getCwd();SkipPath(cwd);snprintf(line, sizeof(line), [%s%s %s] , username, hostname, strlen(cwd) 1 ? / : (cwd 1));printf(%s, line);fflush(stdout); }int GetUserCommand(char command[], size_t size) {char* s fgets(command, size, stdin);if (s NULL) return -1;command[strlen(command) - 1] ZERO;return strlen(command); }void SplitCommand(char command[], int size) {(void)size;gArgv[0] strtok(command, SEP);int index 1;while ((gArgv[index] strtok(NULL, SEP)));}void Die() {exit(1); }void ExecuteCommmand() {pid_t id fork();if (id 0) Die();else if (id 0){// childexecvp(gArgv[0], gArgv);exit(errno);}else {// parentint status 0;pid_t rid waitpid(id, status, 0);if (rid 0){lastcode WEXITSTATUS(status);if (lastcode ! 0) printf(%s:%s:%d\n, gArgv[0], strerror(lastcode), lastcode);}} }void Cd() {// 获取 cd 路径const char* path gArgv[1];if (path NULL) path getHome();// 此时 path 一定存在那么可以直接使用 系统调用 修改工作路径chdir(path);// 获取此时的工作路径char temp[SIZE * 2];getcwd(temp, sizeof(temp));// 拼接 PWD 环境变量snprintf(Cwd, sizeof(Cwd), PWD%s, temp);// 刷新环境变量putenv(Cwd); }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; }int main() {int quit 0;while (!quit){// 自己需要输出一个命令行MakeCommandLineAndPrint();// 获取用户命令字符串char usercommand[SIZE];int num GetUserCommand(usercommand, sizeof(usercommand));if (num 0) return 1;else if (num 0) continue;// 分割用户命令字符串SplitCommand(usercommand, sizeof(usercommand));// 检查命令是否为内建命令num CheckBuildIn();if (num) continue;// 执行命令ExecuteCommmand();}return 0; }
http://www.dnsts.com.cn/news/186048.html

相关文章:

  • 深圳市龙岗区做网站的公司app模板下载网站
  • 建设美食网站的目的和功能定位宁波定制网站建设解决方案
  • 网站怎样快速排名wordpress图片超链接
  • 网站多久备案一次吗房产网排名
  • 炫酷的网站开发国外源代码下载网站
  • 北滘禅城网站建设腾博会的网站是什么
  • 网站建设有哪些分类咸阳做网站公司电话
  • 阅读网站模板怎么把自己的产品推广出去
  • 做网站的工具有哪些烟台网络科技有限公司
  • 建设网站后如何上线wordpress表单提交插件
  • 网站开发实训设计报告福建省住房与城乡建设厅网站
  • 小江高端企业网站建设wordpress下拉框插件
  • 商丘高端网站建设网站怎么做英语和中文的
  • 个人网站备案电话访谈网站关键词字数
  • 西宁整站优化微信官方服务平台
  • 深圳高端品牌网站建设阮一峰的个人网站
  • 多少钱能运营一个网站wordpress 100并发
  • 网站需要哪些费用民治网站建设yihe kj
  • 南昌网站优化可以做哪些网站有哪些
  • 去哪个网站有客户找做标书的洪梅镇网站建设
  • 如何让新网站快速收录网站建设优化汕头
  • 武进区建设局网站昆山 网站建设
  • 手机网站免费生成app可以赚钱做任务的网站有哪些
  • 手机端网站源码wordpress调用文章标题
  • 网站建设好后为什么要维护厦门网站建设网页设计
  • 用dede做的网站首页google网站收录
  • 最好的dm单网站建设个人如何做购物网站 关于支付接口
  • 北京市建设工程质量监督站网站湖南微信网站营销
  • 免费制作网站wordpress免插件
  • 网站网站游戏怎么做阿里云wordpress菜鸟