我们都知道, 计算机技术不但影响着我们的各行各业,Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
在 Linux 中,进程控制有四种状态:创建、退出、等待、替换。为了 验证 或 应用 以上四种进程状态,所以有了下面 minishell 的实现。
Linux 中的 shell ,是指一个面向用户的命令接口,表现形式就是一个可以由用户录入的交互界面,其相当于 Windows 上 cmd 命令行。而下述程序为 shell 程序的简易版,只是简单实现了其中的一部分功能。
shell这个单词的英文含义为“壳”。顾名思义,Shell就像是一个外壳一样。就我理解而言,Shell本身是一段程序,它运行起来后,可以和内核来打交道。它是相对于内核来说的,建立在内核的基础上,面向于用户的一种表现形式。就好比我们看到一个球体,见到的只是外壳,并非内核。
Linux中的shell,是指一个面向用户的命令接口,表现形式就是一个可以由用户录入的界面,这个界面也可以反馈运行信息。
大概阐述
3.Minishell功能
ls -> 查询当前目录文件
ls -a -> 查询当前目录文件包括隐藏文件
ls -l -> 查询当前目录文件详情
touch -> 新建文件
rm -> 删除文件
mkdir -> 新建文件夹
rmdir -> 删除文件夹
cd -> 进入目标文件夹
cp -> 拷贝文件
mv -> 移动/重命名文件
pwd -> 在终端显示当前路径
cat -> 在终端显示文件类型
chmod -> 改变文件权限操作
ln -> 创建文件硬链接
ln -s -> 创建文件软连接
***具有终端输入日记记录功能,time.txt文件实时记录终端情况***
切记 3 个 模块
(1)主模块
(2)功能模块
(3)执行模块
Public头文件
#ifndef __PUBLIC_H__ #define __PUBLIC_H__ #include
#include #include #include #include #include #include #include #include #include #include #include #define MAX_ORDER_LEN 10 #endif
功能模块头文件
#ifndef __TERMINAL_H__ #define __TERMINAL_H__ #define USER "linux@ChenXi:" //用户名 extern void ShowTerminal(void); extern int ReadTerminal(char *pOrder,int maxlen); extern int AnalysisTerminal(char *prOder,char **pAnalysisOrder,int maxlen); extern int DoTerminal(char **pAnalysisOrder,int sum); #endif
执行模块头文件
#ifndef __COMMAND_H__ #define __COMMAND_H__ extern void myls(void); extern void myls_l(void); extern void myls_a(void); extern void mycd(char **AnalysisOrder,int sum); extern void mytouch(char **pAnalysisOrder,int sum); extern void myrm(char **pAnalysisOrder,int sum); extern void mymkdir(char **pAnalysisOrder,int sum); extern void myrmdir(char **pAnalysisOrder,int sum); extern void mycp(char *psrc,char *pdst); extern void mymv(char *old,char *new); extern void mypwd(void); extern void mycat(char *file); extern void Statfile(char *pfilename); extern void GetTime(char *pOrder); extern void mychmod(char *filenum,char *filename); extern void myln(char *file,char *new); extern void myln_s(char *file,char *new); #endif
主模块
#include "Public.h" #include "Command.h" #include "Terminal.h" int main(int argc, char const *argv[]) { char Order[1024] = {0}; //命令数组 char *AnalysisOrder[MAX_ORDER_LEN] = {NULL}; //解析命令指针数组 int sum = 0; //命令模块个数 while(1) { ShowTerminal(); //终端显示 memset(Order,0,sizeof(Order)); // 每次接收命令前清空数组 ReadTerminal(Order,sizeof(Order)); //接收命令 sum = AnalysisTerminal(Order,AnalysisOrder,MAX_ORDER_LEN); //解析命令 DoTerminal(AnalysisOrder,sum); } return 0; }
功能模块
#include "Public.h" #include "Terminal.h" #include "Command.h" /* *终端的显示函数(获取当前文件路径) */ void ShowTerminal(void) { char showbuf[1024] = {0}; //定义存放路径的数组 char *pbuf = NULL; //路径指针 getcwd(showbuf,sizeof(showbuf)); //将当前路径存放进数组 pbuf = showbuf + strlen(showbuf); //指针定位到/0 while ('/' != *pbuf && pbuf >= showbuf) //指针定位到/ { pbuf--; } ++pbuf; //定位到显示路径 printf(USER"/%s#",pbuf); //打印终端显示 //清除读写缓冲区 return; } /* *接受终端命令函数 *传参: (命令数组) (数组大小限制) */ int ReadTerminal(char *pOrder,int maxlen) { fgets(pOrder,maxlen,stdin); //从终端接收命令传进Order数组 pOrder[strlen(pOrder)- 1] = '\0'; //将fgets接到的末尾的\n变为字符串结束标志\0 GetTime(pOrder); return 0; } /* ********解析命令******* *传参:(命令数组)(解析命令指针数组)(数组大小限制) *返回值:一个命令的分块个数 */ int AnalysisTerminal(char *pOrder,char **pAnalysisOrder,int maxlen) { int count = 0; char *pTmp = NULL; //分块一个命令个数的指针 pTmp = strtok(pOrder," "); //接收进第一个命令块 if(NULL == pTmp) //未接受命令返回0 { return 0; } else { pAnalysisOrder[count] = pTmp; //将接收到的第命令(第一个块)放进指针数组 count++; } while(NULL != (pTmp = strtok(NULL," "))) //将其他模块命令依次放入指针数组 { pAnalysisOrder[count] = pTmp; count++; } pAnalysisOrder[count] = NULL; //指针数组最后一位空格给NULL return count ; //返回命令分块个数 } /* ********执行命令******* *传参:(解析命令指针数组)(一个命令的模块数量) *返回值:一个命令的分块个数 */ int DoTerminal(char **pAnalysisOrder,int sum) { /*==========ls类型===============*/ if (1 == sum && !strcmp(pAnalysisOrder[0],"ls")) //pAnalysisOrder[0]是一个指针,不能 == { myls(); } else if (2 == sum && !strcmp(pAnalysisOrder[1],"-l")) { myls_l(); } else if (2 == sum && !strcmp(pAnalysisOrder[1],"-a")) { myls_a(); } /* else if (2 == sum && !strcmp(pAnalysisOrder[1],"文件名")) { myls_filename(); }*/ else if (3 == sum && !strcmp(pAnalysisOrder[1],"-l")) { } /*===========cd切换路径=========*/ if ( !strcmp(pAnalysisOrder[0],"cd")) { mycd(pAnalysisOrder,sum); } /*===========touch创建文件=========*/ if (!strcmp(pAnalysisOrder[0],"touch")) { mytouch(pAnalysisOrder,sum); } /*=========rm删除文件==================*/ if (!strcmp(pAnalysisOrder[0],"rm")) { myrm(pAnalysisOrder,sum); } /*=========mkdi创建文件夹r==================*/ if (!strcmp(pAnalysisOrder[0],"mkdir")) { mymkdir(pAnalysisOrder,sum); } /*=========rmdir删除文件夹==================*/ if (!strcmp(pAnalysisOrder[0],"rmdir")) { myrmdir(pAnalysisOrder,sum); } /*=========cp拷贝==================*/ if (!strcmp(pAnalysisOrder[0],"cp")) { mycp(pAnalysisOrder[1],pAnalysisOrder[2]); } /*=========mv移动/重命名==================*/ if (!strcmp(pAnalysisOrder[0],"mv")) { mymv(pAnalysisOrder[1],pAnalysisOrder[2]); } /*=========pwd获取当前路径==================*/ if (!strcmp(pAnalysisOrder[0],"pwd")) { mypwd(); } /*=========cat将文件打印在终端==================*/ if (!strcmp(pAnalysisOrder[0],"cat")) { mycat(pAnalysisOrder[1]); } /*=========chmod==================*/ if (!strcmp(pAnalysisOrder[0],"chmod")) { mychmod(pAnalysisOrder[1],pAnalysisOrder[2]); } /*=========ln==================*/ if (!strcmp(pAnalysisOrder[0],"ln") && strcmp(pAnalysisOrder[0],"ln")) { myln(pAnalysisOrder[1],pAnalysisOrder[2]); } else if (!strcmp(pAnalysisOrder[0],"ln") && !strcmp(pAnalysisOrder[1],"-s")) { myln_s(pAnalysisOrder[2],pAnalysisOrder[3]); } return 0; }
执行模块
#include "Public.h" #include "Command.h" #include "Terminal.h" void myln(char *file,char *new) { int ret = 4; ret = link(file,new); printf("%d\n",ret); } void myln_s(char *file,char *new) { int ret = 4; ret = symlink(file,new); if(-1 == ret) { perror("fail to ln-s"); } } /* *======日志函数====== */ void GetTime(char *pOrder) { int fd = 0; fd = open("time.txt",O_WRONLY | O_APPEND | O_CREAT,0664); if(-1 == fd) { perror("fail to open time.txt"); return; } struct stat finformation;//存放文件的信息 int ret = 0; ret = lstat("time.txt",&finformation);//获取信息给finformation if(-1 == ret)//判断是否获取成功 { perror("fail to lstat"); return; } struct tm *ptime = NULL;//最近命令时间 char time[128] ={0}; char *mon[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; ptime = localtime(&finformation.st_ctime); sprintf(time," %d年%s %d %d:%d :%d 命令: ",ptime->tm_year+1900,mon[ptime->tm_mon],ptime->tm_mday ,ptime->tm_hour,ptime->tm_min,ptime->tm_sec); write(fd,time,strlen(time)); write(fd,pOrder,strlen(pOrder)); write(fd,"\n",1); close(fd); return; } /* *======myls查看当前目录文件====== */ void myls(void) { DIR *fp = NULL; fp = opendir("."); if(NULL == fp) { perror("fail to opendir(.)"); return; } struct dirent *pfile = NULL; while(NULL != (pfile = readdir(fp))) { if('.' == pfile->d_name[0]) { continue; } printf("%s ",pfile->d_name); } printf("\n"); closedir(fp); return; } /* *======chmod====== */ void mychmod(char *filenum,char *filename) { printf("filenum = %s\n",filenum); printf("filename= %s\n",filename); int modenum = 0; int one = 0; int two = 0; int three = 0; int mode = 0; modenum = atoi(filenum); three = modenum / 100; two = (modenum / 10) % 10; one = modenum % 10; mode = three * 8 * 8 +two * 8 + one; chmod(filename,mode); } /* *======ls_l====== */ void myls_l(void) { DIR *fp = NULL; fp = opendir("."); if(NULL == fp) { perror("fail to opendir(.)"); return; } struct dirent *pfile = NULL; char filename[4096] = {0}; while(NULL != (pfile = readdir(fp))) { if('.' == pfile->d_name[0]) { continue; } sprintf(filename,"%s",pfile->d_name); Statfile(filename); } closedir(fp); return; } void Statfile(char *pfilename) { struct stat finformation;//存放文件的信息 int ret = 0; ret = lstat(pfilename,&finformation);//获取信息给finformation if(-1 == ret)//判断是否获取成功 { perror("fail to lstat"); return; } switch(finformation.st_mode & __S_IFMT)//文件类型 { case __S_IFBLK :putchar('b');break; case __S_IFCHR:putchar('c');break; case __S_IFDIR :putchar('d');break; case __S_IFREG:putchar('-');break; case __S_IFLNK:putchar('l');break; case __S_IFSOCK :putchar('s');break; case __S_IFIFO :putchar('p');break; } finformation.st_mode & S_IRUSR ? putchar('r') : putchar('-');//创建者权限 finformation.st_mode & S_IWUSR ? putchar('w') : putchar('-'); finformation.st_mode & S_IXUSR ? putchar('x') : putchar('-'); finformation.st_mode & S_IRGRP ? putchar('r') : putchar('-');//同组人员权限 finformation.st_mode & S_IWGRP ? putchar('w') : putchar('-'); finformation.st_mode & S_IXGRP ? putchar('x') : putchar('-'); finformation.st_mode & S_IROTH ? putchar('r') : putchar('-');//其余人权限 finformation.st_mode & S_IWOTH ? putchar('w') : putchar('-'); finformation.st_mode & S_IXOTH ? putchar('x') : putchar('-'); printf(" %ld",finformation.st_nlink);//硬链接个数 struct passwd *puid = NULL;//uid名 puid = getpwuid(finformation.st_uid); printf(" %s",puid->pw_name); struct group *pgid = NULL;//gid名 pgid = getgrgid(finformation.st_gid); printf(" %s",pgid->gr_name); printf(" %5ld",finformation.st_size);//文件大小 struct tm *ptime = NULL;//最近编辑时间 char *mon[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; ptime = localtime(&finformation.st_ctime); printf(" %s%d %d:%d %s\n",mon[ptime->tm_mon],ptime->tm_mday,ptime->tm_hour ,ptime->tm_min,pfilename); } /* *======ls_a=========== */ void myls_a(void) { DIR *fp = NULL; fp = opendir("."); if(NULL == fp) { perror("fail to opendir(.)"); return; } struct dirent *pfile = NULL; while(NULL != (pfile = readdir(fp))) { printf("%s ",pfile->d_name); } printf("\n"); closedir(fp); return; } /* *======ls_file=========== */ /* *======ls_l_file=========== */ /* *======cd======切换文件夹 */ void mycd(char **pAnalysisOrder,int sum) { if(NULL != pAnalysisOrder[1]) { chdir(pAnalysisOrder[1]); } return; } /* *======touch======创建文件 */ void mytouch(char **pAnalysisOrder,int sum) { int fd = 0; if(NULL != pAnalysisOrder[1]) { fd = open(pAnalysisOrder[1],O_WRONLY | O_CREAT | O_APPEND,0777);//给写和创建权限 if(-1 == fd) { perror("fail to touch"); return; } } return; } /* *======rm======删除文件 */ void myrm(char **pAnalysisOrder,int sum) { if(NULL != pAnalysisOrder[1]) { remove(pAnalysisOrder[1]); } return; } /* *======mkdir======创建文件夹 */ void mymkdir(char **pAnalysisOrder,int sum) { if(NULL != pAnalysisOrder[1]) { mkdir(pAnalysisOrder[1],0777); } return; } /* *======rmdir======删除文件夹 */ void myrmdir(char **pAnalysisOrder,int sum) { if(NULL != pAnalysisOrder[1]) { rmdir(pAnalysisOrder[1]); } return; } /* *======cp======拷贝文件 */ void mycp(char *psrc,char *pdst) { int fsrc = 0; int fdst = 0; char str[4096] = {0}; fsrc = open(psrc,O_RDONLY); fdst = open(pdst,O_WRONLY | O_TRUNC | O_CREAT,0664); // 110 110 100 if(-1 == fsrc || -1 == fdst) { perror("fail to mycp_open"); return; } read(fsrc,str,sizeof(str)); write(fdst,str,strlen(str)); close(fsrc); close(fdst); return; } /* *======mv======移动重命名 */ void mymv(char *old,char *new) { rename(old,new); return; } /* *======pwd======获取当前路径 */ void mypwd(void) { char path[256] = {0}; getcwd(path,sizeof(path)); printf("%s\n",path); return ; } /* *======cat======文件打印在终端 */ void mycat(char *file) { int ff = 0; char word[8192] = {0}; ff= open(file,O_RDONLY); if(-1 == ff) { perror("fail to mycat"); return; } read(ff,word,sizeof(word)); printf("%s",word); close(ff); return; }