Velvet Star Monitor

Standout celebrity highlights with iconic style.

general

Readline.H history usage in C

Writer Sophia Terry

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 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

2

2 Answers

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.

5

You can get the count of the current (last) entry with int where_history(void). With your example:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<readline/readline.h>
#include<readline/history.h>
#include <string.h>
// ALL CHECKS OMMITTED!
int main()
{ char *s; char *p = getenv("USER"); char *host = getenv("HOSTNAME"); int count = 1; char *ps; printf("USER: %s\n", p); // HOSTNAME does not return anything here, so I skipped it printf("HOST: %s\n", host); // restricting to 32/64 bit ints for simplicity size_t size_int = (sizeof(int) == 4) ? 10 : 20; // env(USER) env(HOSTN...) log_10(MAX_INT) " @:\0" angst-allowance //ps = malloc(strlen(p) + strlen(host) + size_int + 4 + 1); //sprintf(ps, "%d %s@%s:", count, p, host); ps = malloc(strlen(p) + size_int + 4 + 1); sprintf(ps, "%d %s:", count, p); while ((s = readline(ps)) != NULL) { add_history(s); free(s); count++; sprintf(ps, "%d %s:", count, p); } printf("\nlastline:\n"); // That's the line you were looking for, I think. // int where_history(void) returns the current (that is: last) line // HIST_ENTRY *history_get (int) returns the entry data set HIST_ENTRY *entry = history_get(where_history()); printf("%s\n", entry->line); free(ps); exit(EXIT_SUCCESS);
}

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.