应用需求: 应用程序以交互的方式为客户提供服务,比如提供诸如“command1”,“command2”等命令,要求当客户输入时提供类似于终端上的“TAB”,以及上下键寻历史命令的功能。
实验环境:linux 环境,gcc,需要用到以下动态库libreadline.so, libhistory.so, libcurses.so
程序实现:
********************************readline.c************************************************
#include <stdio.h>
#include <sys/types.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <errno.h>
#define NUM 1024
const char *history_file=".test_history";
char History[NUM]; // history_dir/history_file
int Exit;
typedef struct{
const char *name;
int (*handler)();
}CmdFmt;
int test_exit();
int command_common();
CmdFmt command_list[NUM]={
{"Test_1",command_common},
{"Test_2",command_common},
{"Test_exit",test_exit},
NULL
};
int test_exit()
{
Exit=1;
return 0;
}
int command_common()
{
return 0;
}
/*得到运行该程序的客户的家目录*/
char* getuser_dir(int uid)
{
FILE *fp;
char buffer[NUM];
sprintf(buffer,"gawk -F: '{if($3==%d){print $6}}' /etc/passwd",uid);
fp=popen(buffer,"r");
fgets(buffer,strlen(buffer),fp);
pclose(fp);
return strdup(buffer);
}
/*填充该程序的命令表TAB功能*/
static char *
command_generator(const char *text, int state)
{
const char *name;
static int list_index,len;
if(!state)
{
list_index=0;
len = strlen(text);
}
while(name = command_list[list_index].name)
{
list_index++;
if(strncmp(name,text,len) == 0)
{
return strdup(name);
}
}
return ((char *)NULL);
}
/*填充选项命令,该处暂忽略*/
static char *
option_generator(const char *text, int state)
{
static int list_index,len;
return NULL;
}
/*与readline库的命令填充接口*/
char **
readline_command_completion(const char *text, int start, int end)
{
char **matches = (char **)NULL;
if(start == 0)
matches = rl_completion_matches(text,command_generator);
else
matches = rl_completion_matches(text,option_generator);
return matches;
}
/*初始化*/
static int readline_init()
{
char *userdir;
rl_readline_name="Test";
rl_attempted_completion_function = readline_command_completion;
stifle_history(500);
userdir = getuser_dir(getuid());
if(strlen(userdir)>0 && userdir[strlen(userdir)-1]=='\n')
userdir[strlen(userdir)-1]='\0';
sprintf(History,"%s/%s",userdir,history_file);
free(userdir);
read_history(History);
return 0;
}
/*store the commands into History file*/
static int readline_deinit()
{
write_history(History);
return 0;
}
static int command_parse(char *cmdstr)
{
char *name;
char *cmdname;
int list_index=0;
char cmd[NUM];
strcpy(cmd,cmdstr);
cmdname=strtok(cmd," ");
if(cmdname==NULL)
return -1;
while(name=command_list[list_index].name)
{
if(!strcmp(name,cmdname))
{
printf("Find a command defined within program!\n");
command_list[list_index].handler();
return 1;
}
list_index++;
}
return 0;
}
int main()
{
char *r=NULL;
Exit=0;
readline_init();
while(!Exit)
{
if(r!=NULL)
{
free(r);
r=NULL;
}
r=readline("Test#");
add_history(r);
int result;
result=command_parse(r);
if(result < 0)
continue;
else
if(!result)
system(r);
}
readline_deinit();
return 0;
}
***************************************************************************************
编译:
gcc readline.c -o Readline -lreadline -lhistory -lcurses
运行:
略