手搓shell
代码
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#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<0) Die();
else if(id==0)
{
//child
execvp(gArgv[0],gArgv);
exit(errno);
}
else{
//father
int status =0;
pid_t rid = waitpid(id,&status,0);
if(rid>0)
{
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;
}
标签:shell,return,int,char,gArgv,Linux,const,cwd
From: https://blog.csdn.net/W9940/article/details/137525303