shell的简单实现

shell是Unix/Linux中的重要工具,用来解析用户输入的命令。下面我们来实现一个简单的shell程序,来练习fork/exec/wait/exit的使用,顺便推荐一本书籍《Understanding Unix/Linux Programming - A Guide to Theory and Practice》,这本书写的非常好,适合Unix/Linux系统编程初学者使用。

下面是我们shell的主程序:

 1 int main(void)
 2 {
 3     char *cmdline;
 4     char *prompt;
 5     char **arglist;
 6     int result;
 7
 8     prompt = PROMPT;
 9     signal(SIGINT, SIG_IGN);
10     signal(SIGQUIT,SIG_IGN);
11
12     while ((cmdline = next_cmd(prompt, stdin)) != NULL) {
13         if ((arglist = split_line(cmdline)) != NULL) {
14             result = execute(arglist);
15             freelist(arglist);
16         }
17         free(cmdline);
18     }
19
20     return 0;
21 }

其中,next_cmd()函数的主要功能是从输入流中读入下一个命令,碰到文件结束符返回NULL。下面是该函数的代码:

 1 char *next_cmd(char *prompt, FILE *file)
 2 {
 3     char *cmdline;
 4     int  length = 0;
 5     int  c;
 6     int  location = 0;
 7
 8     printf("%s", prompt);
 9
10     while ((c = getc(file)) != ‘\n‘) {
11         if (location + 1 >= length) {
12             cmdline = (char *)malloc(BUFSIZ);
13             length = BUFSIZ;
14         }
15         else if (location >= BUFSIZ) {
16             cmdline = realloc(cmdline, length + BUFSIZ);
17             length += BUFSIZ;
18         }
19         cmdline[location++] = c;
20     }
21     cmdline[location] = ‘\0‘;
22
23     return cmdline;
24 }

split_line()函数的主要功能是将输入的一行字符串拆解成字符串数组,该字符串数组以NULL结束。下面是该函数的代码:

 1 char **split_line(char *cmd)
 2 {
 3     char **arglist;
 4     int  row = 0;
 5     int  len = 0;
 6     char *cp = cmd;
 7     char *start = cmd;
 8     arglist = malloc(BUFSIZ);
 9
10     while (*cp != ‘\0‘) {
11         while (*cp != ‘ ‘ && *cp != ‘\t‘) {
12             ++cp;
13             ++len;
14         }
15         arglist[row] = malloc(len + 1);
16         strncpy(arglist[row], start, len);
17         ++row;
18         len = 0;
19         while (*cp == ‘ ‘ || *cp == ‘\t‘) {
20             ++cp;
21         }
22         start = cp;
23     }
24     arglist[row] = NULL;
25
26     return arglist;
27 }

execute()函数的主要功能是使用fork, execvp和wait函数来运行一个命令,并返回命令的结束状态。下面该函数的代码:

 1 int execute(char **argv)
 2 {
 3     pid_t pid;
 4     int child_info = -1;
 5
 6     if ((pid = fork()) == -1) {
 7         perror("fork error");
 8     }
 9
10     if (pid == 0) {
11         signal(SIGINT, SIG_DFL);
12         signal(SIGQUIT, SIG_DFL);
13         execvp(argv[0], argv);
14         perror("exec error");
15         exit(1);
16     }else {
17         if (wait(&child_info) == -1) {
18             perror("wait error");
19         }
20     }
21
22     return child_info;
23 }

freelist()函数是释放上面分配的字符串数组的空间。下面是该函数的代码:

 1 void freelist(char **list)
 2 {
 3     char **cp = list;
 4     while (*cp) {
 5         free(*cp);
 6         ++cp;
 7     }
 8
 9     free(list);
10 }

由于个人水平有限,欢迎讨论,非喜勿喷,thank you!!

时间: 2024-10-21 21:21:24

shell的简单实现的相关文章

对shell的简单认识

shell是一个命令解释器: shell分为交互式shell和非交互式shell: 交互式shell就是命令行一问一答:非交互式shell是像shell文本那样,一次解析文本, 并未在命令行给我们作出回答. shell又分为登陆式shell和非登录式shell: 主要区分于是否输入用户名和密码,输入用户名.密码登陆就为登陆式shell, 例如我们在图形化界面下打开的终端为非交互式shell: type命令的用法: -t: 加-t参数,type将name通过以下文字显示他的意思 file:表示外部

Shell 实现简单计算器功能

Shell 实现简单计算器功能,脚本如下: [[email protected] scripts]# cat jisuan.sh #!/bin/bash print_usage(){     printf $"USAGE:$0 NUM1 {+|-|*|/} NUM2\n"     exit 1 } #判断传入的参数是不是3个 if [ $# -ne 3 ]   then     print_usage fi firstnum=$1 secondnum=$3 op=$2 #对传入的参数进

使用shell脚本简单模拟对特定文件同时读写操作

使用shell脚本简单模拟对特定文件同时读写操作文件内容的格式:field1    ,       field2    , field3    ,       field4以,为分隔符,但是存在空格. 脚本用法如下: ./check_write_read.sh 10 输出结果: Thu Apr 27 19:59:44 CST 2017:Read operation finished 670 Thu Apr 27 19:59:44 CST 2017:Write operation finished

Ubuntu下Shell的简单实现(C语言)

最近在操作系统的实验课上要求在Linux下实现Shell的简单功能,做了实验感觉挺有收获的,就在这分享一下,欢迎指出问题. 废话不多说,先看main()函数. 1 int main() 2 { 3 char inputBuffer[MAXLINE]; 4 char *argv[MAXLINE/2 - 1]; 5 6 while (1) 7 { 8 printf("COMMAND->"); 9 fgets(inputBuffer,80,stdin); 10 setup(inputB

shell中简单的字符串操作

在SHELL编程中,经常要处理一些字符串变量.比如,计算长度啊.截取子串啊.字符替换啊等等,常常要用到awk.expr.sed.tr等命令.下面给大家介绍个简单的字符串处理方法,用不着嵌套复杂的子命令. ${#VALUE}:计算VALUE字符串的字符数量. ${VALUE%.*}或${VALUE%%.*}:删除VALUE字符串中以分隔符"."匹配的左边字符,保留右边字符. ${VALUE#*.}或${VALUE##*.}:删除VALUE字符串中以分隔符"."匹配的右

shell的简单批量curl接口脚本

shell脚本可以说作用非常大,在服务器领域,用shell操作事务可比手动点击要方便快捷得多了.虽然只是文字界面,但是其强大的处理功能,会让各种操作超乎想象.而且,也可以将这些习惯移植到日常的工作当中,提升办事效率. 其实shell语法很简单,基本上就是综合一下在命令行下,一个个的命令集合,然后就组成了shell脚本.当然了,不懂语法的,百度搜索一下就好了嘛,毕竟,重要的是思想而非语法. 最近,刚接一需求,如下: DBA会将一些服务规则的数据导出,然后一条条手动去curl某应用接口,从而完成相应

shell 文件简单处理

有时候需要简单处理一下文件,用几行shell脚本语句就能搞定,方便快捷,这里记一下,一边下次使用.结合别人的博文和自己的实践,也算原创吧 test1 1 1 1 1 1 test2 2 2 2 2 2 ①paste -d "\t" test1 test2

shell语法简单介绍

一.基本的语法 1.1.shell文件开头 shell文件必须以以下的行開始(必须方在文件的第一行): #!/bin/sh 符号#!用来告诉系统它后面的參数是用来运行该文件的程序.在这个样例中我们使用/bin/sh来运行程序. 当编辑好脚本时,假设要运行该脚本,还必须使其可运行. 要使脚本可运行: 执行chmod +x filename 这样才干用./filename 来执行 1.2 凝视 在进行shell编程时,以#开头的句子表示凝视,直到这一行的结束.我们真诚地建议您在程序中使用凝视. 假设

第十三章、学习 Shell Scripts 简单的 shell script 练习

简单的 shell script 练习 简单范例 对谈式脚本:变量内容由使用者决定 [[email protected] scripts]# vi sh02.sh #!/bin/bash # Program: # User inputs his first name and last name. Program shows his full name. # History: # 2005/08/23 VBird First release PATH=/bin:/sbin:/usr/bin:/us