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