• [Linux]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)) != '
    ') {
    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] = '';
    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 != '') {
    11         while (*cp != ' ' && *cp != '	') {
    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 == '	') {
    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!!

  • 相关阅读:
    windows2008下载
    js代码格式化
    javascript小实例【第二课时笔记】
    学习CSS的一些有效资源
    javascript小实例【第一课时笔记】
    关于HTML5的一些基础知识
    javascript小实例【第三课时笔记】
    c#缓存介绍(转)
    [C#] String与string的区别
    Asp.Net Cache缓存使用代码
  • 原文地址:https://www.cnblogs.com/skycore/p/3991518.html
Copyright © 2020-2023  润新知