编写shell
刺猬@http://blog.youkuaiyun.com/littlehedgehog
编写shell的第一步: 让shell可以执行程序
只有两个要点需要注意,第一,unix/linux提供相应的执行函数exec,我们只需要将我们输入的命令行分解成字符串数组即可。
比如: ls -al 那么我们只需要将这个字符串拆成argv[0]="ls",argv[1]="-al" 即可。 第二点,需要用fork新建一个进程,在子进程中执行我们的命令,即是execvp(argv[0],argv)
代码参照<understanding unix/linux programming>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <signal.h>
- #define BUFSIZE 256
- #define PROMPT "kiss winona $:"
- void setup()
- {
- signal(SIGINT,SIG_IGN);
- signal(SIGQUIT,SIG_IGN);
- }
- void fatal(char *err,int n)
- {
- perror(err);
- exit(n);
- }
- /* 下面是封装malloc 和 remalloc*/
- void * emalloc(size_t n)
- {
- void *ret_p=NULL;
- if((ret_p=malloc(n))!=NULL)
- return ret_p;
- fatal("Out of memory! ",-1);
- }
- void *erealloc(void *p,size_t n)
- {
- void *ret_p=NULL;
- if((ret_p=realloc(ret_p,n))!=NULL)
- return ret_p;
- fatal("Realloc failed! ",-1);
- }
- char * makestr(char *p)
- {
- int len=strlen(p);
- char *ret=emalloc(len+1);
- strncpy(ret,p,len);
- ret[len]='/0';
- return ret;
- }
- /* 我们需要把一个命令行 转化为字符串数组 */
- char ** splitline(char *line)
- {
- char *p;
- char **argv;
- int argc=0;
- if(!line)
- return NULL;
- argv=emalloc(BUFSIZE);
- p=strtok(line," "); //目前只是处理了空格
- while(p)
- {
- argv[argc++]=makestr(p);
- p=strtok(NULL," ");
- }
- argv[argc]=0;
- return argv;
- }
- /* 从标准输入获取命令字符串 注意我们用了个动态空间装载*/
- char * get_cmd(char *prompt,FILE *fp)
- {
- char c;
- char *buffer;
- int pos=0,bufsize=0;
- printf("%s ",prompt);
- if(!fp)
- return NULL;
- while((c=getc(fp))!=EOF)
- {
- if(pos+1>=bufsize)
- {
- if(!bufsize)
- buffer=emalloc(BUFSIZE);
- else
- buffer=erealloc(buffer,bufsize+BUFSIZE);
- bufsize+=BUFSIZE;
- }
- if(c=='/n')
- break;
- buffer[pos++]=c;
- }
- buffer[pos]='/0';
- return buffer;
- }
- /* 小心内存泄露 */
- void freelist(char **argv)
- {
- while(*argv)
- free(*argv++);
- free(argv);
- }
- /* 主要函数: 原理简单 父进程fork一个子进程并等待 子进程执行命令 */
- int execute(char **argv)
- {
- int pid,info=-1;
- if(!argv[0])
- return 0;
- if((pid=fork())==-1)
- fatal("Fork error ",1);
- else if(!pid)
- {
- signal(SIGINT,SIG_DFL);
- signal(SIGQUIT,SIG_DFL);
- execvp(argv[0],argv);
- fatal("command not found ",1);
- }
- else
- {
- if(wait(&info)==-1)
- fatal("wait error ",1);
- return info;
- }
- }
- int main()
- {
- char *cmd=NULL,*prompt=NULL,**argv=NULL;
- prompt=PROMPT;
- setup();
- while((cmd=get_cmd(prompt,stdin))!=NULL)
- {
- if((argv=splitline(cmd))!=NULL)
- {
- execute(argv);
- free(argv);
- }
- free(cmd); //注意cmd也要释放
- }
- return 0;
- }