strtok(buff," ")
;对buff中字符串用空格进行分割(第一步)
strtok(NULL," ")
剩下的都是传的空
ps,ls
这些命令就相当于main.c,是程序员写好的可以直接调用的命令(有执行文件)可以fork替换成它
cd.exit
,这些命令是shell内置的命令(无执行文件,是shell自带的命令),因此下面的程序有多个if语句。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/wait.h>wait()的头文件
#include<pwd.h>得到用户信息的头文件
#include<erron.h>perror的头文件
char* get_cmd(char buff[],char* myargv[])对输入的数据进行分割
{
if(buff==NULL)
{
return NULL;
}
int i=0;
char* s=strtok(buff," ");
while(s!=NULL)
{
myargv[i++]=s;
s=strtok(NULL," ");
}
return myargv[0];
}
void printf_info()
{
printf("\033[1;32mstu@stu-virtual-machile:\033[0m~ $]");用绿颜色显示
int id=getuid();uid表明那个用户运行了这个进程,管理员的id=0;
char* s="$";
if(id==0)
{
s="#";
}
struct passwd* ptr=getpwuid(id);用户名,用man getpwuid可以查看
if(ptr==NULL)
{
printf("$");
fflush(stdout);刷屏,会将缓冲区的内容打印在屏幕上
return;
}
char hostname[64]={0};主机名
if(gethostname(hostname,64)==-1)获取主机名失败
{
printf("$");
fflush(stdout);刷屏,会将缓冲区的内容打印在屏幕上
return;
}
char pwd_buff[128]={0};
if(getcwd(pwd_buff,128)==NULL)绝对路径
{
printf("$");
fflush(stdout);刷屏,会将缓冲区的内容打印在屏幕上
return;
}
printf("\033[1:32m%s@%s %s\033[0m\033[1:34m: %s\033[0m",ptr->pw_name,hostname,pwd_buff,s);s表示是普通用户还是管理员
}
int main()
{
while(1)
{
char buff[128]={0};存放从键盘中获取的命令和参数
//printf("[stu@localhost ~]");
printf_info();
fgets(buff,128,stdin);fgets会在输入的数据后面加\n
buff[strlen(buff)-1]=0;将\n转化为0(\0)
//ls ,ps ,cp a.txt b.txt
char* myargv[10]={0};
char* cmd=get_cmd(buff,myargv);
if(cmd==NULL)
{
continue;
}else if(strcmp(cmd,"exit")==0)
{
break;//exit(0)
}else if(strcmp(cmd,"cd")==0)
{
if(myargv[1]==NULL)
{
continue;
}
if(chdir(myargv[1])==-1)出错返回-1
{
perror("cd err");打印上一句出错的原因
}
continue;
}else
{
//fork+exec
pid_ t pid=fork();
if(pid==-1)
{
printf("fork err\n");
continue;
}
if(pid==0)
{
execvp(cmd,myargv);
printf("execvp err\n");
exit(0);
}
wait(NULL);
}
}
}
pwd函数的实现
pwd可以自己实现,也可以fork()+替换通过bash执行实现
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
iny main()
{
char buff[128]={0};
if(getcwd(buff,128)!=NULL)获得当前程序所处的位置,失败返回空
{
printf("%s",buff);
}
}
ls函数的实现
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<dirent.h>目录流获得的结构体头文件
int main()
{
char buff[128]={0};
if(getcwd(buff,128)==NULL)
{
return 0;如果当前位置获取失败则返回
}
DIR* p=opendir(buff);打开目录流
if(p==NULL)
{
return 0;打开失败返回
}
struct dirent* s=NULL;
while((s=readdir(p))!=NULL)读目录流
{
if(strncmp(s->d_name,".",1)==0).文件为隐藏文件,如果第一个字符为".",则继续,不打印
{
continue;
}
printf("%s ",s->d_name)打印文件名
}
printf("\n");
closedir(p);
return 0;
}
mybash(不依靠fork)
自己写命令函数,自己给路径
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/wait.h>wait()的头文件
#include<pwd.h>得到用户信息的头文件
#include<erron.h>perror的头文件
#define PATH "/home/stu/c219/day08/mybin/ls"ls函数所放路径
char* get_cmd(char buff[],char* myargv[])对输入的数据进行分割
{
if(buff==NULL)
{
return NULL;
}
int i=0;
char* s=strtok(buff," ");
while(s!=NULL)
{
myargv[i++]=s;
s=strtok(NULL," ");
}
return myargv[0];
}
void printf_info()
{
printf("\033[1;32mstu@stu-virtual-machile:\033[0m~ $]");用绿颜色显示
int id=getuid();uid表明那个用户运行了这个进程,管理员的id=0;
char* s="$";
if(id==0)
{
s="#";
}
struct passwd* ptr=getpwuid(id);用户名,用man getpwuid可以查看
if(ptr==NULL)
{
printf("$");
fflush(stdout);刷屏,会将缓冲区的内容打印在屏幕上
return;
}
char hostname[64]={0};主机名
if(gethostname(hostname,64)==-1)获取主机名失败
{
printf("$");
fflush(stdout);刷屏,会将缓冲区的内容打印在屏幕上
return;
}
char pwd_buff[128]={0};
if(getcwd(pwd_buff,128)==NULL)绝对路径
{
printf("$");
fflush(stdout);刷屏,会将缓冲区的内容打印在屏幕上
return;
}
printf("\033[1:32m%s@%s %s\033[0m\033[1:34m: %s\033[0m",ptr->pw_name,hostname,pwd_buff,s);s表示是普通用户还是管理员
}
int main()
{
while(1)
{
char buff[128]={0};存放从键盘中获取的命令和参数
//printf("[stu@localhost ~]");
printf_info();
fgets(buff,128,stdin);fgets会在输入的数据后面加\n
buff[strlen(buff)-1]=0;将\n转化为0(\0)
//ls ,ps ,cp a.txt b.txt
char* myargv[10]={0};
char* cmd=get_cmd(buff,myargv);
if(cmd==NULL)
{
continue;
}else if(strcmp(cmd,"exit")==0)
{
break;//exit(0)
}else if(strcmp(cmd,"cd")==0)
{
if(myargv[1]==NULL)
{
continue;
}
if(chdir(myargv[1])==-1)出错返回-1
{
perror("cd err");打印上一句出错的原因
}
continue;
}else
{
//fork+exec
pid_ t pid=fork();
if(pid==-1)
{
printf("fork err\n");
continue;
}
if(pid==0)
{
char path[128]={0};
if(strncmp(cmd,"./",2)==0||strncmp(cmd,"/",1)==0)
{
strcpy(path,cmd);
}else
{
strcpy(path,PATH);
strcat(path,cmd);拼接
}
execv(path,myargv);
printf("execvp err\n");
exit(0);
}
wait(NULL);
}
}
}