Shell实现代码
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<ctype.h>
#include<pwd.h>
#include<string.h>
void GetLoginName()
{
struct passwd* pass;
pass = getpwuid(getuid());
printf("[%s@",pass->pw_name);
}
void GetHostName()
{
char name[128];
gethostname(name,sizeof(name)-1);
printf("%s",name);
}
void GetDir()
{
char pwd[128];
getcwd(pwd,sizeof(pwd)-1);
int len = strlen(pwd);
char *p = pwd+len-1;
while(*p !='/' && len--)
{
p--;
}
p++;
printf(" %s]#",p);
}
int main()
{
while(1)
{
GetLoginName();
GetHostName();
GetDir();
fflush(stdout);
char buf[1024];
size_t s=read(0,buf,sizeof(buf)-1);
if(s>0)
{
buf[s-1] = 0;
//printf("%s\n",buf);
}
char *_argv[32];
char *start = buf;
_argv[0] = start;
int i = 1;
while(*start)
{
if(*start == ' ')
{
*start = '\0';
start++;
_argv[i++] = start;
}
else
{
start++;
}
}
_argv[i] = NULL;
pid_t id = fork();
if(id ==0)
{
execvp(_argv[0],_argv);
perror("Perror!");
exit(1);
}
else
{
int status = 0;
pid_t ret = waitpid(id,NULL,0);
if(ret > 0)
{
printf("wait success,ret:%d,exitcode:%d,sig:%d\n",\
ret,(status>>8)&0xff,status&0xff);
}
}
}
return 0;
读取命令分析图:
水平有限,首先拿到read()函数所读取到的命令。
ssize_t read(int fd, void *buf, size_t count);
这里是read()函数的原型,上面的代码我们用到了size_t s=read(0,buf,sizeof(buf)-1);
可以看到第一个参数为文件标识符,0对应的是输入流,所以我们可以拿到在命令行输入的字符串。
实现shell的机理是利用进程程序替换。
这里简单说一下这几个函数的区别,
p(path):则第一个参数为路径。
l(list):即把每个命令都当做参数传递。
v(vector):通过指向各参数的指针数组来传递命令。
e(environment):可以传递新的环境变量
这里需要注意的是,l和v不可能同时出现,对于l来说最后一个参数必须为NULL,对于v来说,数组中最后一个指针必须是NULL。