[Linux]shell的简单实现

服务器   发布日期:2025年08月15日   浏览次数:188

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

下面是我们shell的主程序:

 int main(void)
 {
     char *cmdline;
     char *prompt;
     char **arglist;
     int result;
 
     prompt = PROMPT;
     signal(SIGINT, SIG_IGN);
     signal(SIGQUIT,SIG_IGN);
 
     while ((cmdline = next_cmd(prompt, stdin)) != NULL) {
         if ((arglist = split_line(cmdline)) != NULL) {
             result = execute(arglist);
             freelist(arglist);
         }
         free(cmdline);
     }
 
     return ;
 }

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

 char *next_cmd(char *prompt, FILE *file)
 {
     char *cmdline;
     int  length = ;
     int  c;
     int  location = ;
 
     printf("%s", prompt);
 
     while ((c = getc(file)) != '\n') {
         if (location +  >= length) {
             cmdline = (char *)malloc(BUFSIZ);
             length = BUFSIZ;
         } 
         else if (location >= BUFSIZ) {
             cmdline = realloc(cmdline, length + BUFSIZ);
             length += BUFSIZ;
         }
         cmdline[location++] = c;
     }
     cmdline[location] = '\0';
 
     return cmdline;
 }

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

 char **split_line(char *cmd)
 {
     char **arglist;
     int  row = ;
     int  len = ;
     char *cp = cmd;
     char *start = cmd;
     arglist = malloc(BUFSIZ);
 
     while (*cp != '\0') {
         while (*cp != ' ' && *cp != '\t') {
             ++cp;
             ++len;
         }
         arglist[row] = malloc(len + );
         strncpy(arglist[row], start, len);
         ++row;
         len = ;
         while (*cp == ' ' || *cp == '\t') {
             ++cp;
         }
         start = cp;
     }
     arglist[row] = NULL;
 
     return arglist;
 }

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

 int execute(char **argv) 
 {
     pid_t pid;
     int child_info = -;
 
     if ((pid = fork()) == -) {
         perror("fork error");
     }
 
     if (pid == ) {
         signal(SIGINT, SIG_DFL);
         signal(SIGQUIT, SIG_DFL);
         execvp(argv[], argv);
         perror("exec error");
         exit();
     }else {
         if (wait(&child_info) == -) {
             perror("wait error");
         }
     }
 
     return child_info;
 }

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

 void freelist(char **list) 
 {
     char **cp = list;
     while (*cp) {
         free(*cp);
         ++cp;
     }
 
     free(list);
 }

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

以上就是[Linux]shell的简单实现的详细内容,更多关于[Linux]shell的简单实现的资料请关注九品源码其它相关文章!