使用readline库实现应用程序下的仿终端输入模式

应用需求: 应用程序以交互的方式为客户提供服务,比如提供诸如“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

 

运行:

       略

posted on 2012-06-06 15:05  lin_victor  阅读(1975)  评论(0编辑  收藏  举报

导航