类SHELLUI界面C语言实现

类SHELLUI界面C语言实现

2023年8月2日发(作者:)

类SHELLUI界⾯C语⾔实现⼀个在终端实现类Linux shell(cd ls命令)UI界⾯的功能(C语⾔实现)这2天做了⼀个类似Linux shell的UI界⾯,⽬前已初步完成cd, ls, help, pwd, quit等命令,在Linux下实现,效果图见下图:ls命令:开始及help命令:对于完成此UI界⾯来说,最主要是根据输⼊的命令找到相关的命令处理函数。通过参考部分bash的实现,找到了如下⽅法:通过⼀个回调函数指针,实现调⽤相关命令处理函数的功能,代码如下://*****************************************************************************//// Command line function callback type.////*****************************************************************************typedef int (*pfnCmdLine)(int argc, char *argv[]);

//*****************************************************************************////! Structure for an entry in the command list table.////*****************************************************************************typedef struct{ // //! A pointer to a string containing the name of the command. // const char *pcCmd;

// //! A function pointer to the implementation of the command. // pfnCmdLine pfnCmd;

// //! A pointer to a string of brief help text for the command. // const char *pcHelp;}tCmdLineEntry;⽽终端输⼊的命令最终会在CmdLineProcess()这个核⼼函数⾥⾯进⾏处理,代码如下:int CmdLineProcess(char *pcCmdLine){ static char *argv[CMDLINE_MAX_ARGS + 1]; char *pcChar; int argc; int bFindArg = 1; tCmdLineEntry *pCmdEntry;

// // Initialize the argument counter, and point to the beginning of the // command line string. // argc = 0; pcChar = pcCmdLine;

//printf("CmdLineProcess: %sn", pcCmdLine);

// // Advance through the command line until a zero character is found. // while (*pcChar) { // // If there is a space, then replace it with a zero, and set the flag // to search for the next argument. // if(*pcChar == ' ') { *pcChar = 0; bFindArg = 1; }

// // Otherwise it is not a space, so it must be a character that is part // of an argument. // else { // // If bFindArg is set, then that means we are looking for the start // of the next argument. // if(bFindArg) { // // As long as the maximum number of arguments has not been // reached, then save the pointer to the start of this new arg // in the argv array, and increment the count of args, argc. // if(argc < CMDLINE_MAX_ARGS) { //printf("nargc=%d, argv=%s ", argc, argv); //printf(" pcChar=%c ", *pcChar);

argv[argc] = pcChar;

//printf("nargc=%d, argv=%s ", argc, argv);

argc++; bFindArg = 0; }

// // The maximum number of arguments has been reached so return // the error. // else { return(CMDLINE_TOO_MANY_ARGS); } } }

// // Advance to the next character in the command line. // pcChar++; }

//printf("argc=%d, argv=%s ", argc, argv);

// // If one or more arguments was found, then process the command. // if(argc) { // // Start at the beginning of the command table, to look for a matching // command. // pCmdEntry = &g_sCmdTable[0];

//printf("pCmdEntry->pcCmd=%s n", pCmdEntry->pcCmd);

// // Search through the command table until a null command string is // found, which marks the end of the table. // while(pCmdEntry->pcCmd) { //printf("while: pCmdEntry->pcCmd=%s, argv[0]=%s n", pCmdEntry->pcCmd, argv[0]); //printf("while: pCmdEntry->pfnCmd=0x%x n", pCmdEntry->pfnCmd);

// // If this command entry command string matches argv[0], then call // the function for this command, passing the command line // arguments. // if(!strcmp(argv[0], pCmdEntry->pcCmd)) { //printf("Define: pCmdEntry->pcCmd=%s, argv[0]=%s n", pCmdEntry->pcCmd, argv[0]); //printf("***pCmdEntry->pfnCmd=0x%x n", pCmdEntry->pfnCmd);

return(pCmdEntry->pfnCmd(argc, argv)); }

// // Not found, so advance to the next entry. // pCmdEntry++; } }

// // Fall through to here means that no matching command was found, so return // an error. // return(CMDLINE_BAD_CMD);}参考了部分⽹上的资料,实现Linux "ls" 命令的源码如下:/************************************************************************************** File: - Z:workcodeclongluocmd_ls.c** VENDOR_EDIT** Copyright (C), tcpipstack.**

** Description:

** cmd_ls.c - The implement of the Linux Like "ls" command.**

** Version: 1.0** Date created: 10:20:56,14/11/2012** Author: **

** --------------------------- Revision History: --------------------------------** **

************************************************************************************/

#include #include #include #include #include #include #include #include #include #include

int do_ls(char *dir,char *filename,int lflag){ int n; struct stat buf; char out[100]; struct passwd *pw; struct group *gr; struct tm *t;

//如果不带l参数,直接显⽰⽂件/⽬录名 if (lflag == 0)

{ printf("%st", filename); return 0; }

if(lstat(dir,&buf)<0) { fprintf(stderr,"stat error:%sn",strerror(errno)); return -1; }

//获取字符串的属性:普通⽂件-、⽬录d、字符设备c、块设备b、 //管道⽂件p、连接⽂件l、套接字⽂件s switch(_mode & S_IFMT)

{ case S_IFREG:

printf("-"); break; case S_IFDIR:

printf("d"); break; case S_IFCHR:

printf("c"); break; case S_IFBLK:

printf("b"); break; case S_IFIFO:

printf("p"); break; case S_IFLNK:

printf("l"); break; case S_IFSOCK:

printf("s"); break; }

//打印⽂件的读写属性:读r、写w、执⾏x、⽆权限- for(n=8;n>=0;n--)

{ if(_mode&(1<

//硬链接数,此链接⾮彼链接,指(包含)⽬录的个数, //⽂件为1,⽬录起始为2,再加上⽬录⾥包含的⽬录个数(不递归,只⼀层) printf(" %d",_nlink);

pw = getpwuid(_uid); //所属⽤户名 printf(" %s",pw->pw_name);

gr = getgrgid(_gid); //所属组名 printf(" %s",gr->gr_name);

printf(" %ld",_size); //字节计总⼤⼩

t = localtime(&_atime); //最后⼀次访问时间 printf(" %d-%d-%d %d:%d" ,t->tm_year+1900 ,t->tm_mon+1 ,t->tm_mday ,t->tm_hour ,t->tm_min); printf(" %s ",filename);

//判断是否为链接,是返回真

if(S_ISLNK(_mode))

{ printf(" -> "); if(readlink(filename,out,100)==-1) { //printf("readlink errorn"); } printf("%s",out); } printf("n");

return 0;}

// ls的准备⼯作int ls_prepare(char *w,int aflag,int lflag)

{ struct stat buf; //man lstat可以看到此结构 char name[100];

DIR *dir; //类似打开⽂件的fd描述符 struct dirent *pdr; //man readdir可以看到此结构

//获取⽂件/⽬录属性并赋值给buf,该函数和lstat⼀样, //只是当w为链接时,指代他本⾝,并不存在⽂件 if(lstat(w,&buf)<0)

{ fprintf(stderr,"stat error:%sn",strerror(errno)); return -1; }

if(S_ISDIR(_mode)) //判断是否为⽬录,是返回真 { dir = opendir(w); //打开⽬录 while ((pdr = readdir(dir))!=NULL) //读/遍历⽬录 { if(aflag==0) //如果不带a参数,越过以.开头的所有⽂件/⽬录 {

if(pdr->d_name[0]=='.') continue; memset(name,0,100);

strcpy(name,w); //拷贝 strcat(name,"/"); //追加 strcat(name,pdr->d_name); do_ls(name,pdr->d_name,lflag); } //有a参数显⽰所有 else

{ memset(name,0,100); strcpy(name,w); strcat(name,"/"); strcat(name,pdr->d_name); do_ls(name,pdr->d_name,lflag); } } closedir(dir); } //为⽂件则直接显⽰ else

{ do_ls(w,w,lflag); }

return 0;}项⽬的main函数代码如下,主要就是⼀个while(1)循环读取终端的输⼊,然后送⼊命令处理函数,值得注意的是因为输⼊了换⾏符,因此需要对输⼊的字符进⾏处理,否则会有bug产⽣:int main(int argc, char *argv[]){ int nStatus, nStrLen;

fprintf(stderr, "Hello, CMD ");

// Enter an infinite loop for reading and processing commands from the user. while (1) { // Print a prompt to the console. Show the CWD. printf("n%s> ", g_cCwdBuf);

// Get a line of text from the user. fgets(g_cCmdBuf, CMD_BUF_SIZE, stdin);

// Remove the char 'n'. nStrLen = strlen(g_cCmdBuf); if ('n' == g_cCmdBuf[nStrLen - 1]) { g_cCmdBuf[nStrLen - 1] = '0'; }

// Pass the line from the user to the command processor. // It will be parsed and valid commands executed. nStatus = CmdLineProcess(g_cCmdBuf);

// Handle the case of bad command. if(nStatus == CMDLINE_BAD_CMD) { printf("Bad command!n"); } // Handle the case of too many arguments. else if(nStatus == CMDLINE_TOO_MANY_ARGS) { printf("Too many arguments for command processor!n"); } // Otherwise the command was executed. Print the error // code if one was returned. else if(nStatus != 0) { printf("Command returned error code.n"); } }

return 0;}在编写这个⼩项⽬的同时,也顺便把Makefile的编写也复习了下,这个项⽬的Makefile⽂件如下:## Makefile - Rules for building the program.#

# History:# , 12/11/2012, created it.# , 13/11/2012, modified it.## The compiler to be COMPILERCOMPILER=gccendif# Definitions for using (${COMPILER}, gcc)# The command for calling the =gcc# The flags passed to the =-Wall -Os -c# The command for calling the =ld# The flags passed to the S=--gc-sections# The PHONY targets.

.PHONY: all clean# The default rule, which causes the Application to be : cmd_ui# The rule to create the target directory.${COMPILER}: mkdir ${COMPILER}# The rule for building the object file from each C source file.%.o : %.c ${CC} ${CFLAGS} -D${COMPILER} -o $@ $<# The =cmdline.o cmd_ui_shell.o cmd_ls.o# The final executable =cmd_ui

# The rule for building the _ui: ${OBJS} $(CC) -o $@ $?# The rule to clean out all the build : rm -f ${wildcard *.o} ${exec}

endif以上,这个项⽬可以应⽤在其他终端上,⽐如串⼝上实现简单的UI界⾯:-)

发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1690920609a463832.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信