summary refs log tree commit diff
path: root/bin/cash/libedit/history.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/cash/libedit/history.c')
-rw-r--r--bin/cash/libedit/history.c90
1 files changed, 89 insertions, 1 deletions
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;