標籤: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的簡單實現