项目目标
1.编写函数打印初始界面以及显示输入的命令(由于程序一直执行,需要在循环内执行)
2.编写接收用户输入的命令的函数
3.编写使命令与功能匹配的函数
4.将界面输入的字符串分割为命令以及传入函数的数据
5.完成minishell的基本功能函数:
ls :显示目录下文件(不包括隐藏文件)
ls -a :显示所有文件
touch :创建一个文件
rm:移除一个文件
mkdir :创建一个目录
rmdir:移除一个目录
cd :切换目录
cp:拷贝文件
mv:移动文件内容
pwd:显示当前目录
cat:显示文件内容
chmod :改变文件权限
ln:创造文件链接
2.5.(补充任务)将输入的命令写入时间日志
6.将不同文件下的函数建立关联
7.将函数进行封装
目标一的实现:
使用printf函数打印出基础界面,再用getcwd获得本地目录的值,由于值过于长,因此通过while以及if的判断,将打印出来的内容只显示最后一个子目录
其实现子函数如下:
int show(void)
{char tmp[1024]={0};char *ptm=NULL;getcwd(tmp,sizeof(tmp));ptm=tmp;while(*ptm !='\0'){ptm++;}while(*ptm !='/'){ptm--;}if(strcmp(tmp,"/")!=0){ptm++;}printf("[linux@ubuntu:%s]",ptm);
}
目标二的实现:
在主函数中设置一个数组,将其传输到目标二的函数中,用fgets函数将界面上输入的值写入数组中(用stdin),并在数组的最后一项补充‘\0’-----作用为:在目标三中使匹配能够完成。
//主函数中定义数组pcmd(maxlen);
int getuse(char *pcmd,int maxlen)
{fgets(pcmd,maxlen,stdin);pcmd[strlen(pcmd)-1]='\0';
}
目标三与四的实现:
将目标二中的数组与预设的命令符号通过strncmp对比,若符合,通过strtok函数对数组中的字符串按空格进行切割,在分别用指针保存切割后的指令,一般第一个指令为命令,后面的指令为输入参数。
int str(char *cmd)
{
if(!strcmp(cmd,"exit")){break;}if(!strncmp(cmd,"cd",2)){char *token=strtok(cmd," ");token =strtok(NULL," ");cd(token);}if(!strncmp(cmd,"cp",2)){char *age=NULL;char *agv=NULL;char *token=strtok(cmd," ");age =strtok(NULL," ");agv =strtok(NULL," ");cp(age,agv);}if(!strncmp(cmd,"chmod",5)){char *age=NULL;char *agv=NULL;char *token=strtok(cmd," ");age =strtok(NULL," ");agv =strtok(NULL," ");mychmod(age,agv);}if(!strncmp(cmd,"ls-l",4)){char *token=strtok(cmd," ");token =strtok(NULL," ");lsl(token);}if(!strcmp(cmd,"ls")){ls();}if(!strncmp(cmd,"ls-a",4)){lsa();}if(!strncmp(cmd,"mkdir",5)){char *token=strtok(cmd," ");token =strtok(NULL," ");mymkdir(token);}if(!strncmp(cmd,"rmdir",5)){char *token=strtok(cmd," ");token =strtok(NULL," ");myrmdir(token);}if(!strncmp(cmd,"ln",2)){char *age=NULL;char *agv=NULL;char *token=strtok(cmd," ");age=strtok(NULL," ");agv=strtok(NULL," ");ln(age,agv);}if(!strncmp(cmd,"mv",2)){char *age=NULL;char *agv=NULL;char *token=strtok(cmd," ");age =strtok(NULL," ");agv =strtok(NULL," ");mv(age,agv);}if(!strncmp(cmd,"touch",5)){char *token=strtok(cmd," ");token =strtok(NULL," ");touch(token);}if(!strncmp(cmd,"cat",3)){char *token=strtok(cmd," ");token =strtok(NULL," ");cat(token);}if(!strncmp(cmd,"rm",2)){char *token=strtok(cmd," ");token =strtok(NULL," ");rm(token);}if(!strcmp(cmd,"pwd")){pwd();}
}
目标五的实现
按照ubantu的shell中的基本功能函数编写函数:
ls功能:先使用getcwd函数获得目录地址,用opendir打开目录,并通过readdir读取目录,当读取到空时停止读取,读取到隐藏目录时,跳过,并将读取到的目录打印出来
#include"head.h"
int ls(void)
{char *a=NULL;DIR *b=NULL;struct dirent *c=NULL;char *ml=NULL;a=getcwd(ml,256);b=opendir(a);while(1){c=readdir(b);if(NULL==c){break;}if('.'==c->d_name[0]){continue;}printf(" %s ",c->d_name);}printf("\n");return 0;
}
ls -a功能:将ls的功能删减跳过隐藏文件即可
touch功能:使用fopen函数,打开方式为w即可
#include"head.h"
int touch(char *agv)
{FILE *a=NULL;char *p=NULL;p=agv;a=fopen(p,"w");fclose(a);
}
rm功能:使用remove函数
mkdir功能 :使用mkdir函数
rmdir:使用rmdir函数
cd :使用chdir函数
mv:使用rename函数
pwd:使用getcwd函数获得目录并打印
ln:使用link函数链接ab文件
cat:使用r方式打开文件,并将内容存到数组中,使用fputc函数将数组内容打印到终端上
#include"head.h"
int cat(char *q)
{FILE *tmp=NULL;char d;tmp=fopen(q,"r");while(1){d=fgetc(tmp);fputc(d,stdout);if(d==EOF){break;}}printf("\n");
}
chmod :先将从终端输入的字符型数字改变为八进制数字(strtol函数),然后使用chmod函数
#include"head.h"
int mychmod(char *age,char *agv)
{mode_t mode =0;mode =strtol(agv,NULL,8);printf("%d",mode);chmod(age,mode);
}
cp:将传入的文件用r打开并存到数组中,用w打开传入的目标文件,用fgetc得到数组中的内容,用fputc写入目标文件即可
#include"head.h"
int cp(char *age,char *agv)
{FILE *tmp=NULL;FILE *aim=NULL;char *a=NULL;char *b=NULL;a=age;b=agv;char c[4096]={0};char d;tmp=fopen(a,"r");aim=fopen(b,"w");while(1){d=fgetc(tmp);fputc(d,aim);if(d==EOF){break;}}
}
目标六的实现
1.创造一个包含目标5实现的函数的声明的头文件,并包括各个函数所需的头文件
#ifndef __HEAD_H__
#define __HEAD_H__
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<dirent.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>
#include<stdlib.h>
#include<string.h>
extern int ls(void);
extern int lsa(void);
extern int lsl(const char *agv);
extern int touch(char *agv);
extern int rm(char *agv);
extern int mymkdir(char *agv);
extern int myrmdir(char *agv);
extern int cd(char *agv);
extern int cp(char *age,char *agv);
extern int mv(char *age,char *agv);
extern int pwd(void);
extern int mychmod(char *age,char *agv);
extern int cat(char *q);
extern int ln(char *age,char *agv);#endif
2.使用Makefile将所有有关文件关联并用make一起编译
OBJ=a.out
OBJT=main.c touch.c cd.c ls-l.c ls.c ls-a.c mkdir.c rmdir.c cat.c rm.c pwd.c cp.c mv.c ln.c chmod.c $(OBJ):$(OBJT)gcc $^ -o $@
目标七的实现
用tar -zxvf a.out tar.gz 将a.out压缩,a.out即为应用名,运行文件名可以在Makefile中更改,压缩包就是应用包。
附:目标2.5与主函数
目标2.5:在getuse中使用fopen用w打开一个文件,对文件写入存有输入命令的数组以及输入时间。
int getuse(char *pcmd,int maxlen)
{FILE *a=NULL;time_t c;struct tm *d=NULL;fgets(pcmd,maxlen,stdin);pcmd[strlen(pcmd)-1]='\0';time(&c);d =localtime(&c);a=fopen("day.txt","a+");fprintf(a,"[%04d-%02d-%02d %02d:%02d:%02d]\n",d->tm_year+1900,d->tm_mon+1,d->tm_mday,d->tm_hour,d->tm_min,d->tm_sec);fwrite(pcmd,25,1,a);fputc('\n',a);fclose(a);
}
主函数将getuse、show、str包含即可。