From 51138625d23a39786d6c5a01cc39a55e5c9f5db5 Mon Sep 17 00:00:00 2001 From: June McEnroe Date: Fri, 18 Jan 2019 16:47:32 -0500 Subject: Add H_SAVE_INCR function to libedit --- bin/cash/libedit/editline.3 | 12 ++++++ bin/cash/libedit/histedit.h | 2 + bin/cash/libedit/history.c | 90 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 103 insertions(+), 1 deletion(-) diff --git a/bin/cash/libedit/editline.3 b/bin/cash/libedit/editline.3 index 37bc035b..96ea5282 100644 --- a/bin/cash/libedit/editline.3 +++ b/bin/cash/libedit/editline.3 @@ -838,11 +838,23 @@ Load the history list stored in .It Dv H_SAVE , Fa "const char *file" Save the history list to .Fa file . +.It Dv H_SAVE_INCR , Fa "const char *file" +Append the history list since the previous event +.Fa ev +to +.Fa file . .It Dv H_SAVE_FP , Fa "FILE *fp" Save the history list to the opened .Ft FILE pointer .Fa fp . +.It Dv H_SAVE_FP_INCR , Fa "FILE *fp" +Append the history list since the previous event +.Fa ev +to the opened +.Ft FILE +pointer +.Fa fp . .It Dv H_SETUNIQUE , Fa "int unique" Set flag that adjacent identical event strings should not be entered into the history. diff --git a/bin/cash/libedit/histedit.h b/bin/cash/libedit/histedit.h index 9ea71899..a6bdee48 100644 --- a/bin/cash/libedit/histedit.h +++ b/bin/cash/libedit/histedit.h @@ -226,6 +226,8 @@ int history(History *, HistEvent *, int, ...); #define H_DELDATA 24 /* , int, histdata_t *);*/ #define H_REPLACE 25 /* , const char *, histdata_t); */ #define H_SAVE_FP 26 /* , FILE *); */ +#define H_SAVE_INCR 27 /* , const char *); */ +#define H_SAVE_FP_INCR 28 /* , FILE *); */ diff --git a/bin/cash/libedit/history.c b/bin/cash/libedit/history.c index cf6b5789..bb5a654f 100644 --- a/bin/cash/libedit/history.c +++ b/bin/cash/libedit/history.c @@ -869,7 +869,7 @@ history_save_fp(TYPE(History) *h, FILE *fp) oomem: h_free(ptr); done: - flock(fileno(fp), LOCK_UN); + (void) flock(fileno(fp), LOCK_UN); return i; } @@ -893,6 +893,82 @@ history_save(TYPE(History) *h, const char *fname) } +static int +history_save_fp_incr(TYPE(History) *h, TYPE(HistEvent) *ev, FILE *fp) +{ + char *line = NULL; + char *ptr; + const char *str; + int i = -1, retval; + size_t len, max_size; + size_t llen = 0; + ssize_t sz; +#ifndef NARROWCHAR + static ct_buffer_t conv; +#endif + + if (flock(fileno(fp), LOCK_EX) == -1) + goto done; + if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) + goto done; + + if (fseek(fp, 0, SEEK_SET) == -1) + goto done; + if ((sz = getline(&line, &llen, fp)) == -1) + goto done; + if (strncmp(line, hist_cookie, (size_t)sz) != 0) + goto done; + if (fseek(fp, 0, SEEK_END) == -1) + goto done; + if (sz == 0) + if (fputs(hist_cookie, fp) == EOF) + goto done; + + ptr = h_malloc((max_size = 1024) * sizeof(*ptr)); + if (ptr == NULL) + goto done; + for (i = 0, retval = HPREV(h, ev); + retval != -1; + retval = HPREV(h, ev), i++) { + str = ct_encode_string(ev->str, &conv); + len = strlen(str) * 4 + 1; + if (len > max_size) { + char *nptr; + max_size = (len + 1024) & (size_t)~1023; + nptr = h_realloc(ptr, max_size * sizeof(*ptr)); + if (nptr == NULL) { + i = -1; + goto oomem; + } + ptr = nptr; + } + (void) strvis(ptr, str, VIS_WHITE); + (void) fprintf(fp, "%s\n", ptr); + } +oomem: + h_free(ptr); +done: + (void) flock(fileno(fp), LOCK_UN); + return i; +} + + +static int +history_save_incr(TYPE(History) *h, TYPE(HistEvent) *ev, const char *fname) +{ + FILE *fp; + int i; + + if ((fp = fopen(fname, "a+")) == NULL) + return -1; + + i = history_save_fp_incr(h, ev, fp); + + (void) fclose(fp); + return i; +} + + /* history_prev_event(): * Find the previous event, with number given */ @@ -1073,12 +1149,24 @@ FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...) he_seterrev(ev, _HE_HIST_WRITE); break; + case H_SAVE_INCR: + retval = history_save_incr(h, ev, va_arg(va, const char *)); + if (retval == -1) + he_seterrev(ev, _HE_HIST_WRITE); + break; + case H_SAVE_FP: retval = history_save_fp(h, va_arg(va, FILE *)); if (retval == -1) he_seterrev(ev, _HE_HIST_WRITE); break; + case H_SAVE_FP_INCR: + retval = history_save_fp_incr(h, ev, va_arg(va, FILE *)); + if (retval == -1) + he_seterrev(ev, _HE_HIST_WRITE); + break; + case H_PREV_EVENT: retval = history_prev_event(h, ev, va_arg(va, int)); break; -- cgit 1.4.1