user2245682 user2245682 - 4 months ago 25
C Question

Readline.H history usage in C

Good Morning,

I'm trying to get the last command to write inside of my C program. Right now It is just taking a command and adding it to history.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<readline/readline.h>
#include<readline/history.h>

int main(int argc, char **argv){
char *s;
char *p = getenv("USER");
char *host =getenv("HOSTNAME");
int count = 1;
char *ps;
sprintf(ps, "%d %s@%s:", count, p, host);


while (s=readline(ps)){
add_history(s);
free(s);
count++;
sprintf(ps, "%d %s@%s:", count, p, host);
}
return 0;
}


I see from the manual located here https://cnswww.cns.cwru.edu/php/chet/readline/history.html That I'm unable to get information from history without using Function:

HIST_ENTRY * history_get (int offset)


Does anyone have an example of readline history? I'm having trouble wrapping my mind around this concept.

Thank you

Answer

Continuing from the comments, your primary issue was you provided only an uninitialized pointer with no memory allocated for ps. While you are free to dynamically allocate ps, simply using automatic storage is sufficient, e.g.:

char ps[MAXC] = "";  /* where MAXC is a constant of sufficient size */

In addition to getting a single entry, the readline and history library provides the ability to retrieve the entire history list for a session. For example to retrieve a history session, history_list () will return an allocated array of type HIST_ENTRY ** containing the history for the session. A short example of its use would be:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<readline/readline.h>
#include<readline/history.h>

enum { MAXC = 128 };

int main (void){

    char ps[MAXC] = "", 
        *p = getenv("USER"),
        *host = getenv("HOSTNAME"),
        *s = NULL; 
    int count = 1;
    sprintf(ps, "%d %s@%s> ", count, p, host);

    using_history();    /* initialize history */

    while ((s = readline(ps))) {
        if (strcmp (s, "quit") == 0) {
            free (s);
            break;
        }
        add_history (s);
        free (s);
        count++;
        sprintf (ps, "%d %s@%s> ", count, p, host);
    }

    /* get the state of your history list (offset, length, size) */
    HISTORY_STATE *myhist = history_get_history_state ();

    /* retrieve the history list */
    HIST_ENTRY **mylist = history_list ();

    printf ("\nsession history for %s@%s\n\n", p, host);
    for (int i = 0; i < myhist->length; i++) { /* output history list */
        printf (" %8s  %s\n", mylist[i]->line, mylist[i]->timestamp);
        free_history_entry (mylist[i]);     /* free allocated entries */
    }
    putchar ('\n');

    free (myhist);  /* free HIST_ENTRY list */
    free (mylist);  /* free HISTORY_STATE   */

    return 0;
}

Example Use/Output

$ ./bin/readline
1 david@alchemy> command 1
2 david@alchemy> command 2
3 david@alchemy> command 3
4 david@alchemy> quit

session history for david@alchemy

 command 1
 command 2
 command 3

Look things over and let me know if you have any further questions.