手搓shell
代码
#include #include #include #include #include #include #include #define ZERO '\0' #define SIZE 512 #define SEP " " #define NUM 32 #define Skiopath(p) do{ p += strlen(p-1);while(*p!='/')p--;}while(0) char *gArgv[NUM]; char cwd[SIZE*2]; int lastcode =0; void Die() { exit(1); } const char *Gethome() { const char *home =getenv("HOME"); if(home==NULL)return "/"; return home; } const char *GetuserName() { const char *name= getenv("USER"); if(name==NULL)return "None"; return name; } const char *GethostName() { const char *hostname = getenv("HOSTNAME"); if(hostname==NULL)return "None"; return hostname; } const char *GetCwd() { const char *cwd=getenv("PWD"); if(cwd==NULL)return "None"; return cwd; } void Makecommandline_print() { char line[SIZE]; const char *username = GetuserName(); const char *hostname = GethostName(); const char *cwd = GetCwd(); Skiopath(cwd); snprintf(line,SIZE,"[%s@%s %s]> ",username,hostname,strlen(cwd)==1?"/":cwd+1); printf("%s",line); fflush(stdout); } int Getusercommand(char command[],size_t n) { char *s = fgets(command,n,stdin); if(s==NULL)return 1; command[strlen(command)-1]=ZERO; return strlen(command); } void Splitcommand(char command[],size_t n) { //"ls -a -l -n"-> "ls" "-a" "-l" "-n" gArgv[0] = strtok(command,SEP); int index =1; while((gArgv[index++]=strtok(NULL,SEP)));//done,故意写成=,表示先赋值,在判断。分割之后,strtok会返回NULL,刚好让gArgv最后一个元素是NULL,并且while判断结束 } void Executecommand() { pid_t id =fork(); if(id //child execvp(gArgv[0],gArgv); exit(errno); } else{ //father int status =0; pid_t rid = waitpid(id,&status,0); if(rid0) { lastcode = WEXITSTATUS(status); if(lastcode!=0)printf("%s:%s:%d\n",gArgv[0],strerror(lastcode),lastcode); } } } void Cd() { const char *path = gArgv[1]; if(path==NULL)path=Gethome(); //path 一定存在 chdir(path); //刷新环境变量 char temp[SIZE*2]; getcwd(temp,sizeof(temp)); //导环境变量 snprintf(cwd,sizeof(cwd),"PWD=%s",temp); putenv(cwd); } int Checkbuilding() { int yes =0; const char *enter_cmd = gArgv[0]; if(strcmp(enter_cmd,"cd")==0) { yes =1; Cd(); } else if(strcmp(enter_cmd,"echo")==0&&strcmp(gArgv[1],"$?")==0) { yes=1; printf("%d\n",lastcode); lastcode=0; } return yes; } int main() { int quit =0 ; while(!quit) { //1.输出一个命令行 Makecommandline_print(); //2.获取用户命令字符串 char usercommand[SIZE]; int n = Getusercommand(usercommand,sizeof(usercommand)); //3.命令行字符串分割 Splitcommand(usercommand,sizeof(usercommand)); //4.检查命令是否是内建命令 n=Checkbuilding(); if(n)continue; //n.执行命令 Executecommand(); } return 0; }

(图片来源网络,侵删)