编写程序,实现shell功能——项目训练——day08

c

c今天做了一个实战项目训练,编写一个程序,实现shell功能,我们称之为minishell。

主要是利用Linux中IO接口实现,实现的功能有:

        1.ls        ls -a        ls -l        cd        cp        mv        pwd        cat        

        2.touch        rm        mkdir        rmdir        chmod        ln

首先,我们先进行编写主函数main.c

#include "head.h"    //包含各种头文件
#include "terminal.h"    
#include "record.h"   int main(void)
{char command[1024] = {0};    //接收字符串,定义到主函数是因为都要用到    char *parg[10] = {NULL};    //指针数组int curcmdlen = 0;          //查看输入InitRecord();while(1){ShowTerminal();                //显示终端GetCommand(command,1024);        //获取命令if(!strcmp(command,"exit"))    //如果输入的是exit退出{break;}RecordCommand(command);        //存储历史命令,做记录curcmdlen = SplitCommand(command,parg,10);    ExecCommand(parg,curcmdlen);    //输出}return 0;
}

head.h主要包含了所需要的头文件

#ifndef __HEAD_H__
#define __HEAD_H__#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<dirent.h>
#include<string.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>
#include<stdlib.h>#endif

接下来就开始编写函数terminal.c以及terminal.h了

#include"head.h"
#include "command.h"
/**********************************函数名:ShowTerminal*参  数:*		缺省*返回值:*		成功返回0
********************************/
int ShowTerminal(void)
{char tmpbuff[1024] = {0};char *ptmp = NULL;getcwd(tmpbuff,sizeof(tmpbuff));/*获得路径中最后一段目录文件名*/ptmp = tmpbuff + strlen(tmpbuff);while(*ptmp != '/'){--ptmp;}if(strcmp(tmpbuff,"/")){++ptmp;}printf("[linux@linux:%s]:",ptmp);return 0;
}/*********************************************************函数名:GetCommand*参  数:*		pcmdbuf:存放命令空间首地址*		maxlen:最大存放字符串个数*返回值:*		成功返回0*		失败返回-1*******************************************************/
int GetCommand(char *pcmdbuf,int maxlen)
{fgets(pcmdbuf,maxlen,stdin);pcmdbuf[strlen(pcmdbuf)-1] = '\0';return 0;
}/*********************************************************函数名:SplitCommand*参  数:*		pcmdbuf:存放命令空间首地址*		parg:存放解析后字符串地址的指针数组*		maxlen:最多解析命令的个数*返回值:*		成功返回解析到命令的个数*		失败返回-1*******************************************************/
int SplitCommand(char *pcmdbuf,char **parg,int maxlen)
{char *ptmp = NULL;int cnt = 0;ptmp = pcmdbuf;parg[cnt] = strtok(ptmp," ");cnt++;while(1)    //切割字符串{parg[cnt] = strtok(NULL," ");if(NULL == parg[cnt]){break;}cnt++;}return cnt;
}/*********************************************************函数名:ExecCommand*参  数:*		parg:存放解析后字符串地址的指针数组*		curlen:命令的个数*返回值:*		成功返回0*		失败返回-1*******************************************************/
int ExecCommand(char **parg,int curlen)
{if(!strcmp(parg[0],"ls")){MyLs(curlen,parg);}else if(!strcmp(parg[0],"cd")){MyCd(curlen,parg);}else if(!strcmp(parg[0],"touch")){MyTouch(curlen,parg);}else if(!strcmp(parg[0],"rm")){MyRm(curlen,parg);}else if(!strcmp(parg[0],"mkdir")){MyMkdir(curlen,parg);}else if(!strcmp(parg[0],"rmdir")){MyRmdir(curlen,parg);}else if(!strcmp(parg[0],"cp")){MyCp(curlen,parg);}else if(!strcmp(parg[0],"mv")){MyMv(curlen,parg);}else if(!strcmp(parg[0],"pwd")){MyPwd(curlen,parg);}else if(!strcmp(parg[0],"cat")){MyCat(curlen,parg);}else if(!strcmp(parg[0],"chmod")){MyChmod(curlen,parg);}else if(!strcmp(parg[0],"ln")){MyLn(curlen,parg);}return 0;
}

terminal.h文件

#ifndef __TERMINAL_H__
#define __TERMINAL_H__extern int ShowTerminal(void); 
extern int GetCommand(char *pcmdbuf,int maxlen);
extern int SplitCommand(char *pcmdbuf,char **parg,int maxlen);
extern int ExecCommand(char **parg,int curlen);#endif

接下来就是开始写命令函数了:command.c

#include"head.h"/*********************************************************函数名:MyCd*参  数:*		argc:命令的个数*		argv:存放解析后字符串地址的指针数组*返回值:*		成功返回0*		失败返回-1 *******************************************************/
int MyCd(int argc,char *argv[])
{if(argv[1] != NULL){chdir(argv[1]);}return 0;
}
int MyLs(int argc,char *argv[])
{DIR *dp = NULL;struct dirent *pp = NULL;struct passwd *pwd = NULL;struct group *grp = NULL;struct stat buf;struct tm *ptm = NULL;char tmpbuff[1024] = {0};int ret = 0;char *mon[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};dp = opendir(".");if(NULL == dp){perror("fail to opendir");return -1;}if(1 == argc){while((pp = readdir(dp)) != NULL){if('.' == *pp->d_name){continue;}printf("%-15s",pp->d_name);++ret;if(0 == ret % 5){putchar('\n');}}if(ret != 5){putchar('\n');}}if(2 == argc && !strcmp(argv[1],"-a")){while((pp = readdir(dp)) != NULL){printf("%-15s",pp->d_name);++ret;if(0 == ret % 5){putchar('\n');}}if(ret != 5){putchar('\n');}}if(2 == argc && !strcmp(argv[1],"-l")){while(1){pp = readdir(dp);if(NULL == pp){break;}if('.' == pp->d_name[0]){continue;}ret = lstat(pp->d_name,&buf);if(-1 == ret){perror("fail to stat");return -1;}switch(buf.st_mode & S_IFMT){case S_IFBLK:putchar('b');break;case S_IFCHR:putchar('c');break;case S_IFDIR:putchar('d');break;case S_IFIFO:putchar('p');break;case S_IFLNK:putchar('l');break;case S_IFREG:putchar('-');break;case S_IFSOCK:putchar('s');break;}buf.st_mode & S_IRUSR ? putchar('r'):putchar('-');buf.st_mode & S_IWUSR ? putchar('w'):putchar('-');buf.st_mode & S_IXUSR ? putchar('x'):putchar('-');buf.st_mode & S_IRGRP ? putchar('r'):putchar('-');buf.st_mode & S_IWGRP ? putchar('w'):putchar('-');buf.st_mode & S_IXGRP ? putchar('x'):putchar('-');buf.st_mode & S_IROTH ? putchar('r'):putchar('-');buf.st_mode & S_IWOTH ? putchar('w'):putchar('-');buf.st_mode & S_IXOTH ? putchar('x'):putchar('-');printf(" %ld",buf.st_nlink);pwd = getpwuid(buf.st_uid);if(NULL == pwd){printf(" %d",buf.st_uid);}else{printf(" %s",pwd->pw_name);}grp = getgrgid(buf.st_gid);if(NULL == grp){printf(" %d",buf.st_gid);}else{printf(" %s",grp->gr_name);}printf(" %5ld",buf.st_size);ptm = localtime(&buf.st_mtime);printf(" %s  %02d %02d:%02d",mon[ptm->tm_mon],ptm->tm_mday,ptm->tm_hour,ptm->tm_min);printf(" %s",pp->d_name);if(S_ISLNK(buf.st_mode)){readlink(pp->d_name,tmpbuff,sizeof(tmpbuff));printf(" -> %s",tmpbuff);}putchar('\n');}}closedir(dp);return 0;
}int MyTouch(int argc,char *argv[])
{FILE *p = NULL;int i = 0;for(i = 1;i < argc;++i){p = fopen(argv[i],"a");fclose(p);}return 0;
}int MyRm(int argc,char *argv[])
{int i = 0;for(i = 1;i < argc;++i){remove(argv[i]);}return 0;
}int MyMkdir(int argc,char *argv[])
{int i = 0;for(i = 1;i < argc;++i){mkdir(argv[i],0777);}return 0;
}int MyRmdir(int argc,char *argv[])
{int i = 0;for(i = 1;i < argc;++i){rmdir(argv[i]);}return 0;
}int MyCp(int argc,char *argv[])
{FILE *p = NULL;FILE *q = NULL;char ch[4096] = {0};p = fopen(argv[1],"r");q = fopen(argv[2],"a");while(1){if(NULL == fgets(ch,sizeof(ch),p)){break;}fputs(ch,q);}fclose(p);fclose(q);return 0;
}int MyMv(int argc,char *argv[])
{if(0 != rename(argv[1],argv[2])){perror("Error");return -1;}return 0;
}int MyPwd(int argc,char *argv[])
{char tmpbuff[4096] = {0};getcwd(tmpbuff,sizeof(tmpbuff));printf("%s\n",tmpbuff);return 0;
}int MyCat(int argc,char *argv[])
{FILE *fp = NULL;fp = fopen(argv[1],"r");char tmpbuff[4096] = {0};if(NULL == fp){perror("fail to fopen");return 0;}while(NULL != fgets(tmpbuff,sizeof(tmpbuff),fp)){printf("%s",tmpbuff);}fclose(fp);return 0;
}int MyChmod(int argc,char *argv[])
{char *fp = NULL;char *mode_str = NULL;mode_t mode = 0;fp = argv[1];mode_str = argv[2];mode = strtol(mode_str,NULL,8);chmod(fp,mode);return 0;
}int MyLn(int argc,char *argv[])
{link(argv[1],argv[2]);return 0;
}

command.h:

cat command.h
#ifndef __COMMAND_H__
#define __COMMAND_H__extern int MyLs(int argc,char *argv[]);
extern int MyCd(int argc,char *argv[]);
extern int MyTouch(int argc,char *argv[]);
extern int MyRm(int argc,char *argv[]);
extern int MyMkdir(int argc,char *argv[]);
extern int MyRmdir(int argc,char *argv[]);
extern int MyCp(int argc,char *argv[]);
extern int MyMv(int argc,char *argv[]);
extern int MyPwd(int argc,char *argv[]);
extern int MyCat(int argc,char *argv[]);
extern int MyChmod(int argc,char *argv[]);
extern int MyLn(int argc,char *argv[]);#endif

还有就是创建一个历史记录,使操作过的命令都有记录

record.c

#include "head.h"
#include "record.h"FILE *fp = NULL;/*********************************************************函数名:InitRecord*参  数:*		缺省 void*返回值:*		成功返回0*		失败返回-1*******************************************************/
int InitRecord(void)
{fp = fopen(RECORD_PATH,"a");if(NULL == fp){perror("fail to fopen");return -1;}return 0;
}/*********************************************************函数名:RecordCommand*参  数:*		pcmdbuf 命令字符串首地址*返回值:*		成功返回0*		失败返回-1*******************************************************/
int RecordCommand(char *pcmdbuf)
{time_t t;struct tm *ptm = NULL;time(&t);ptm = localtime(&t);fprintf(fp,"[%04d-%02d-%02d %02d:%02d:%02d]%s\n",ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec,pcmdbuf);fflush(fp);return 0;
}/*********************************************************函数名:DeInitRecord*参  数:*		缺省 void*返回值:*		成功返回0*		失败返回-1*******************************************************/
int DeInitRecord(void)
{if(fp != NULL){fclose(fp);fp = NULL;}return 0;
}

record.h

#ifndef __RECORD_H__
#define __RECORD_H__#define RECORD_PATH "./record.txt"extern int InitRecord(void);
extern int RecordCommand(char *pcmdbuf);
extern int DeInitRecord(void);#endif

以上,我们就实现了minishell操作了

接下来给大家演示一下:

先实现的是ls        ls -a        ls -l

实现了:touch        rm        mkdir        rmdir        cd         cp        cat

实现了:mv        pwd        chmod

实现了:ln以及历史记录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/261988.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序 ---- 慕尚花坊 项目初始化

目录 项目介绍 01. 项目概述 02. 项目演示 03. 项目技术栈 04. 接口文档 申请开发权限 项目初始化 01. 创建项目与项目初始化 02. 自定义构建 npm 集成Sass 03. 集成项目页面文件 04. VsCode 开发小程序项目 项目介绍 01. 项目概述 [慕尚花坊] 是一款 同城鲜花订购…

2024.02.22作业

1. 将互斥机制的代码实现重新敲一遍 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <…

DC与DCT DCG的区别

先进工艺不再wire load model进行静态时序分析&#xff0c;否则综合结果与后端物理电路差距很大&#xff0c;因此DC综合工具也进行了多次迭代&#xff0c;DC工具有两种模式&#xff0c;包括wire load mode和Topographical Mode&#xff0c;也就是对应的DC Expert和DC Ultra。 …

Linux课程三课---Linux开发环境的使用(yum的相关)

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

Python-pdfplumber读取PDF内容

文章目录 前言一、pdfplumber模块1.1 pdfplumber的特点1.2 pdfplumber.PDF类1.3pdfplumber.Page类 二 pdfplumber的使用2.1 加载PDF2.2 pdfplumber.PDF 类2.3 pdfplumber.Page 类2.4 读取PDF2.5 读取PDF文档信息2.6 查看总页数2.7 查看总页数读取第一页的宽度&#xff0c;页高等…

B端系统:工作台页面,如何从平庸走向出众

Hi&#xff0c;大家好&#xff0c;我是贝格前端工场&#xff0c;从事8年前端开发的老司机。大家看过很多平庸的工作台页面&#xff0c;但是仔细分析过平庸的表现吗&#xff0c;仔细思考过如何实现出众的效果吗&#xff1f;这篇文章为你解读。 一、工作台页面是什么&#xff0c;…

【前端素材】推荐优质后台管理系统Xoric平台模板(附源码)

一、需求分析 当我们从多个层次来详细分析后台管理系统时&#xff0c;可以将其功能和定义进一步细分&#xff0c;以便更好地理解其在不同方面的作用和实际运作。 1. 功能层次 a. 用户管理功能&#xff1a; 用户注册和登录&#xff1a;管理用户账户的注册和登录过程。权限管…

【前端】前端三要素之DOM

写在前面&#xff1a;本文仅包含DOM内容&#xff0c;JavaScript传送门在这里&#xff0c;BOM传送门在这里。 本文内容是假期中刷的黑马Pink老师视频&#xff08;十分感谢Pink老师&#xff09;&#xff0c;原文保存在个人的GitLab中&#xff0c;如果需要写的网页内容信息等可以评…

OpenCV人脸检测案例实战

人脸检测是一种计算机视觉技术&#xff0c;旨在识别图像或视频中的人脸。这项技术的基本内容包括使用特定的算法和模型来定位和识别人脸&#xff0c;通常涉及在图像中寻找面部特征&#xff0c;如眼睛、鼻子、嘴巴等&#xff0c;以便准确地确定人脸的位置和边界。人脸检测技术的…

MySQL 窗口函数温故知新

本文用于复习数据库窗口函数&#xff0c;希望能够温故知新&#xff0c;也希望读到这篇文章的有所收获。 本文以&#xff1a;MySQL为例 参考文档&#xff1a; https://www.begtut.com/mysql/mysql-window-functions.html 使用的样例数据&#xff1a;https://www.begtut.com/m…

9.vue学习笔记(组件传递Props校验+组件事件-组件传递数据+组件事件-配合“v-model”使用)

文章目录 1.组件传递Props校验1.1.默认值1.2.必选项1.3.注意事项&#xff1a;props 是只读的 2.组件事件-组件传递数据2.1.温馨提示&#xff1a;组件之间传递数据的方案 3.组件事件-配合“v-model”使用 1.组件传递Props校验 Vue组件可以更细致地声明对传入的 props 的校验要求…

学习鸿蒙一定要搞清楚的几个概念

目录 1、UI框架 2、应用模型 2.1、应用模型介绍 2.2、两种应用模型 2.3、应用模型和UI框架的关系 3、Ability 3.1、Ability介绍 3.2、FA模型的ability 3.3、Stage模型的Ability 1、UI框架 HarmonyOS提供了一套UI(User Interface,用户界面)开发框架&#xff0c;即方舟…

java 课程签到管理系统Myeclipse开发mysql数据库web结构jsp编程servlet计算机网页项目

一、源码特点 java 课程签到管理系统是一套完善的java web信息管理系统 采用serlvetdaobean&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0…

OpenGauss数据库本地搭建并结合内网穿透实现远程访问

文章目录 前言1. Linux 安装 openGauss2. Linux 安装cpolar3. 创建openGauss主节点端口号公网地址4. 远程连接openGauss5. 固定连接TCP公网地址6. 固定地址连接测试 前言 openGauss是一款开源关系型数据库管理系统&#xff0c;采用木兰宽松许可证v2发行。openGauss内核深度融合…

专业140+总分420+南京信息工程大学811信号与系统考研经验南信大电子信息与通信工程,真题,大纲,参考书

今年顺利被南信大电子信息录取&#xff0c;初试420&#xff0c;专业811信号与系统140&#xff08;Jenny老师辅导班上140很多&#xff0c;真是大佬云集&#xff09;&#xff0c;今年应该是南信大电子信息最卷的一年&#xff0c;复试线比往年提高了很多&#xff0c;录取平均分380…

来分析两道小题

一、源码 二、分析 首先它会接两个参数一个是id一个是ps&#xff0c;传递的话会包含一个flag.php&#xff0c;然后数据库连接&#xff0c;之后传递过滤&#xff0c;然后查询&#xff0c;如果查到了就会取id&#xff0c;取出来看是不是跟adog一样&#xff0c;如果是它告诉你账号…

会声会影2024新功能及剪辑视频步骤教程

会声会影2024的新功能主要包括&#xff1a; 全新的标题动态与特效&#xff1a;用户可以为文字标题指定进入、中场和退出的不同动态效果&#xff0c;比如闪现进入、中场弹跳和淡出退出等&#xff0c;让文字标题更具动感。此外&#xff0c;还新增了多个标题特效&#xff0c;包括…

软考-中级-系统集成2023年综合知识(一)

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 软考中级专栏回顾 专栏…

由面试题“Redis是否为单线程”引发的思考

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…

【大数据】Flink 之部署篇

Flink 之部署篇 1.概述和参考架构2.可重复的资源清理3.部署模式3.1 Application 模式3.2 Per-Job 模式&#xff08;已废弃&#xff09;3.3 Session 模式 Flink 是一个多用途框架&#xff0c;支持多种不同的混合部署方案。下面&#xff0c;我们将简要介绍 Flink 集群的构建模块、…