码迷,mamicode.com
首页 > 其他好文 > 详细

shell的简单实现

时间:2014-09-24 21:50:47      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   使用   ar   strong   for   文件   

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!!

shell的简单实现

标签:style   blog   color   io   使用   ar   strong   for   文件   

原文地址:http://www.cnblogs.com/skycore/p/3991518.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!