这是一个模拟shell端的程序。
使用了execvp,fork,wait,malloc,realloc以及strtok()函数。
smsh.h
1 char* next_cmd(); 2 char** splitline(char* ); 3 void freelist(char **); 4 int execute(char** );
smsh1.c
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <signal.h> 5 #define DFL_PROMPT ">:" 6 int main(){ 7 char * cmdline, *prompt, **arglist; 8 int i; 9 void setup(); 10 prompt = DFL_PROMPT; 11 setup(); 12 while((cmdline=next_cmd(prompt, stdin)) != NULL ){ 13 if((arglist=splitline(cmdline))!=NULL){ 14 for(i=0; i<2; i++) 15 printf("%s ", arglist[i]); 16 printf(" "); 17 printf("will execute. "); 18 execute(arglist); 19 freelist(arglist); 20 } 21 free(cmdline); 22 } 23 24 return 0; 25 } 26 void setup(){ 27 /* 28 * purpose: initialize shell 29 * 在shell中忽略信号SIGINT&SIGQUIT, 但是在子进程中恢复对 30 * SIGINT&SIGQUIT的默认操作,允许用户通过按表示结束多文件多Ctrl-D来退出 31 */ 32 signal(SIGINT, SIG_IGN); 33 signal(SIGQUIT, SIG_IGN); 34 }
splitline.c
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include "smsh.h" 5 6 char* next_cmd(char* prompt, FILE *fp){ 7 /* 8 * purpose: read next command line from fp 9 * return: dynamically allocated string holding command line 10 * note: allocates space in BUFSIZ chunks.其中BUFSIZ是库函数中define过了的 11 */ 12 char* buf; 13 int bufspace = 0; 14 int pos = 0; 15 int c; 16 //printf("%s", prompt); 17 while((c=getc(fp)) != EOF) { 18 if(pos+1>=bufspace) { 19 if(bufspace==0) 20 buf = malloc(BUFSIZ); 21 else 22 buf = realloc(buf, bufspace+BUFSIZ); 23 bufspace+=BUFSIZ; 24 } 25 if(c==' ') 26 break; 27 buf[pos++]=c; 28 } 29 if(c==EOF || pos==0) 30 return NULL; 31 buf[pos]=0; 32 //printf("u cin is end. "); 33 return buf; 34 } 35 36 char** splitline(char* cmdline){ 37 /* 38 * purpose: split a line 39 * note:注意:在最后一次给arglist赋值时,也就是strtok()返回为NULL的时候,也需要给 40 * arglist[i]=malloc(sizeof(char*));一下,即使最后赋的为NULL也需要分配一个指针空间给它。 41 */ 42 char **arglist; 43 char *delim=" "; 44 char *cmdbuf; 45 int i=1; 46 cmdbuf=strtok(cmdline,delim); 47 //printf("cmdbuf0: %s ", cmdbuf); 48 arglist = malloc(sizeof(char*)); 49 arglist[0]=malloc(strlen(cmdbuf)*sizeof(char)); 50 strcpy(arglist[0], cmdbuf); 51 while((cmdbuf=strtok(NULL, delim))) { 52 arglist = realloc(arglist, (1+i)*sizeof(char*)); 53 arglist[i]=malloc(strlen(cmdbuf)*sizeof(char)); 54 strcpy(arglist[i], cmdbuf); 55 //printf("cmdbuf%d: %s ",i,cmdbuf); 56 i++; 57 } 58 arglist[i]=malloc(sizeof(char*)); 59 arglist[i]=NULL; 60 return arglist; 61 }
execute.c
1 /* execute.c- code used by small shell to execute commands 2 */ 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <unistd.h> 6 #include <signal.h> 7 #include <sys/wait.h> 8 9 int execute(char** arglist){ 10 /* 11 *purpose: run a program passing it arguments; 12 *return: status returned via wait, or -1 on error 13 *errors: -1 on fork() on wait() errors 14 */ 15 int pid; 16 int child_info = -1; 17 printf("now its go into the function execute "); 18 if((pid=fork()) == -1) 19 perror("fork"); 20 else if(pid == 0) { 21 signal(SIGINT, SIG_DFL); 22 signal(SIGQUIT, SIG_DFL); 23 execvp(arglist[0], arglist); 24 perror("cannot execute command"); 25 exit(1); 26 } 27 else { 28 if(wait(&child_info) == -1) 29 perror("wait"); 30 } 31 return child_info; 32 } 33 void freelist(char** list) { 34 /* 35 *purpose: free the list returned by splitline 36 *returns: nothing 37 *actoin: free all strings in list and then free the list 38 */ 39 char **cp=list; 40 while(*cp) 41 free(*cp++); 42 free(list); 43 }
关于为什么要开一个进程给execvp()使用,是因为unix运行一个程序;1.将指定的程序复制到调用它的进程。2.将指定的字符串数组作为argv[]传给这个程序。3.运行这个程序。
如果不开进程就来执行execvp(),就会运行完一个命令后就会结束退出。这是因为execvp()用命令指定的程序代码覆盖了shell的程序代码,然后在命令指定的程序结束之后就退出。