无极小说网,长沙优化网站分析,长沙网站推广排名,淘宝客网站名今天进行了linux系统高级编程io阶段学习的结尾#xff0c;完成了一个minshell的小项目。
一、项目介绍
利用Linux中IO接口实现MiniShell#xff0c;实现常用的shell指令的实现。
项目想要实现需要思考的地方有#xff1a;
1.如何打印终端命令
2.如何接受终端命令
3.实现对…今天进行了linux系统高级编程io阶段学习的结尾完成了一个minshell的小项目。
一、项目介绍
利用Linux中IO接口实现MiniShell实现常用的shell指令的实现。
项目想要实现需要思考的地方有
1.如何打印终端命令
2.如何接受终端命令
3.实现对应的命令
要求采用多文件编程并实现按时间将输入的指令记录到日志文件中。二、项目实现
初步思考整个项目的大致流程图如下 接下来介绍项目实现中的一些关键部分
2.1 打印终端提示符 要实现如上图的终端命令提示符我们可以发现该提示符主要分为两部分
1.前面的linuxubuntu是固定不变的直接printf输出即可后面的路径则是一直改变的这时我们可以通过getcwd函数来实现获取当前的绝对路径int Terminal(void)
{char buf[1024] {0};char *p NULL;getcwd(buf,sizeof(buf));p buf;while(*p ! \0) //主要打印当前的一级路径即可则可以通过指针分割出我们想要的路径{p;}while(*p ! /){p--;}p;printf(\033[1;31m); //这里主要采用vt100打印出想要的字符颜色printf(linuxUbuntu:);printf(\033[0m);printf(\033[1;35m);printf(%s,p);printf(\033[0m);printf($ );return 0;
}实现效果如下
2.2用户指令的获取
这里采用fgets获取用户键盘输入的指令
int Gets(char *tmbuff,int maxlen)
{fgets(tmbuff,maxlen,stdin);tmbuff[strlen(tmbuff)-1] \0; //将fgets获取到的字符串末尾的换行符删掉return 0;
}2.3用户指令的分割
我们在输入shell指令时有些指令并不是一个单独的指令另外还包括了参数以及操作对象等用上面的方法获取的字符串往往是一整串每个指令之间还包括了空格这时我们就需要去分割出来每个部分。 有两种实现方法
第一种直接采用strtok函数对字符串进行分割。 以下是strtok函数的功能介绍
char *strtok(char *str, const char *delim);
将字符串分解为一个由零个或多个非空记号组成的序列。在第一次调用strtok()
时要解析的字符串应该在str中指定。在每个应该解析相同字符串的后续调用中
str必须为NULL。
以下是实现代码#include string.h
#include stdio.hint main(void)
{char cmdbuf[1024] {0};char *pret NULL;char *parg[10] {NULL};int cnt 0;//ln -s file.txt a.txtgets(cmdbuf);parg[cnt] strtok(cmdbuf, );//以空格进行分割cnt;while (1){parg[cnt] strtok(NULL, ); //后续分割第一个参数传入NULLif (NULL parg[cnt]){break;}cnt;}int i 0;for (i 0; i cnt; i){printf(parg[%d] %s\n, i, parg[i]);}return 0;
}第二种是编写函数采用一个可移动指针去移动到空格出并置‘\0’从而实现对字符串的分割
int SplitCommand(char *pcmdbuf, char **parg, int maxlen)
{char *ptmp NULL;int cnt 0;ptmp pcmdbuf;while (1){parg[cnt] ptmp;cnt;while (*ptmp ! \0 *ptmp ! ){ptmp;}if (\0 *ptmp){break;}*ptmp \0;ptmp;while (*ptmp ){ptmp;}}return cnt;
}2.4 日志文件的创建
这里直接用标准io的相关接口函数进行即可
#include record.h
#include stdio.h
#include time.hFILE *fp NULL;/*********************************************************函数名:InitRecord*参 数:* 缺省 void *返回值:* 成功返回0 * 失败返回-1 *******************************************************/
int InitRecord(void)
{fp fopen(RECORD_PATH, a);if (NULL fp){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_mon1, 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;
}
项目主函数代码展示
#include stdio.h
#include string.h
#include terminal.h
#include record.hint main(void)
{char command[1024] {0};char *parg[10] {NULL};int curcmdlen 0;InitRecord();while (1){ShowTerminal();GetCommand(command, 1024);if (!strcmp(command, exit)){DeInitRecord();break;}RecordCommand(command);curcmdlen SplitCommand(command, parg, 10);ExecCommand(parg, curcmdlen);}return 0;
}三、项目总结
通过本次项目进一步加深了对文件io以及标准io相关函数的了解进一步加强了在遇到问题时解决问题的能力项目过程中令我影响最深刻的就是在获取用户输入的指令时一开始在另外一个文件中定义了一个数组用来存放获取的指令导致之后运行时指令数据莫名消失通过排查才发现对于这种程序一直都会到处使用的数据应该注意其的存在时间因为如果将指令存放在一个函数中就会导致这样一个局部变量在函数运行结束后这个数据就会消失所以应该将其定义在主函数中或者定义为全局变量。