diff --git a/check.t b/check.t index 53f1ba1..34aa403 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.697 2015/07/05 17:04:24 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.698 2015/07/05 19:37:11 tg Exp $ # -*- mode: sh -*- #- # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, @@ -30,7 +30,7 @@ # (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date expected-stdout: - @(#)MIRBSD KSH R51 2015/06/28 + @(#)MIRBSD KSH R51 2015/07/05 description: Check version of shell. stdin: @@ -39,7 +39,7 @@ name: KSH_VERSION category: shell:legacy-no --- expected-stdout: - @(#)LEGACY KSH R51 2015/06/28 + @(#)LEGACY KSH R51 2015/07/05 description: Check version of legacy shell. stdin: diff --git a/edit.c b/edit.c index bc8cc2c..ad29d93 100644 --- a/edit.c +++ b/edit.c @@ -28,7 +28,7 @@ #ifndef MKSH_NO_CMDLINE_EDITING -__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.286 2015/05/03 11:28:53 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.287 2015/07/05 19:37:13 tg Exp $"); /* * in later versions we might use libtermcap for this, but since external @@ -3054,7 +3054,7 @@ x_edit_line(int c MKSH_A_UNUSED) } if (modified) { *xep = '\0'; - histsave(&source->line, xbuf, true, true); + histsave(&source->line, xbuf, HIST_STORE, true); x_arg = 0; } else x_arg = source->line - (histptr - x_histp); @@ -4311,8 +4311,8 @@ vi_cmd(int argcnt, const char *cmd) return (-1); if (modified) { es->cbuf[es->linelen] = '\0'; - histsave(&source->line, es->cbuf, true, - true); + histsave(&source->line, es->cbuf, + HIST_STORE, true); } else argcnt = source->line + 1 - (hlast - hnum); diff --git a/funcs.c b/funcs.c index b2b04fb..64c7d2f 100644 --- a/funcs.c +++ b/funcs.c @@ -38,7 +38,7 @@ #endif #endif -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.275 2015/07/05 17:50:39 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.276 2015/07/05 19:37:14 tg Exp $"); #if HAVE_KILLPG /* @@ -442,7 +442,7 @@ c_print(const char **wp) if (flags & PO_HIST) { Xput(xs, xp, '\0'); - histsave(&source->line, Xstring(xs, xp), true, false); + histsave(&source->line, Xstring(xs, xp), HIST_STORE, false); Xfree(xs, xp); } else { int len = Xlength(xs, xp); @@ -2076,7 +2076,7 @@ c_read(const char **wp) } if (savehist) - histsave(&source->line, Xstring(xs, xp), true, false); + histsave(&source->line, Xstring(xs, xp), HIST_STORE, false); ccp = cp = Xclose(xs, xp); expanding = false; diff --git a/histrap.c b/histrap.c index 4e3136d..320ce77 100644 --- a/histrap.c +++ b/histrap.c @@ -27,7 +27,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.146 2015/07/05 17:04:26 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.147 2015/07/05 19:37:15 tg Exp $"); Trap sigtraps[ksh_NSIG + 1]; static struct sigaction Sigact_ign; @@ -380,7 +380,7 @@ hist_execute(char *cmd, Area *areap) last_line = hist_source->line; } - histsave(&hist_source->line, cmd, true, true); + histsave(&hist_source->line, cmd, HIST_STORE, true); /* now *histptr == cmd without all trailing newlines */ afree(cmd, areap); cmd = *histptr; @@ -620,31 +620,67 @@ histsync(void) * save command in history */ void -histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups) +histsave(int *lnp, const char *cmd, int svmode, bool ignoredups) { - char **hp; - char *c; + static char *enqueued = NULL; + char **hp, *c; const char *ccp; + if (svmode == HIST_APPEND) { + if (!enqueued) + svmode = HIST_STORE; + } else if (enqueued) { + c = enqueued; + enqueued = NULL; + --*lnp; + histsave(lnp, c, HIST_STORE, true); + afree(c, APERM); + } + + if (svmode == HIST_FLUSH) + return; + ccp = cmd + strlen(cmd); while (ccp > cmd && ccp[-1] == '\n') --ccp; strndupx(c, cmd, ccp - cmd, APERM); - if (ignoredups && !strcmp(c, *histptr) + if (svmode != HIST_APPEND) { + if (ignoredups && !strcmp(c, *histptr) #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY - && !histsync() + && !histsync() #endif - ) { + ) { + afree(c, APERM); + return; + } + ++*lnp; + } + +#if HAVE_PERSISTENT_HISTORY + if (svmode == HIST_STORE && histfd != -1) + writehistfile(*lnp, c); +#endif + + if (svmode == HIST_QUEUE || svmode == HIST_APPEND) { + size_t nenq, ncmd; + + if (!enqueued) { + if (*c) + enqueued = c; + else + afree(c, APERM); + return; + } + + nenq = strlen(enqueued); + ncmd = strlen(c); + enqueued = aresize(enqueued, nenq + 1 + ncmd + 1, APERM); + enqueued[nenq] = '\n'; + memcpy(enqueued + nenq + 1, c, ncmd + 1); afree(c, APERM); return; } - ++*lnp; - -#if HAVE_PERSISTENT_HISTORY - if (dowrite && histfd != -1) - writehistfile(*lnp, c); -#endif hp = histptr; @@ -855,7 +891,7 @@ histload(Source *s, unsigned char *base, size_t bytes) } } else { s->line = lno--; - histsave(&lno, (char *)(base + 4), false, false); + histsave(&lno, (char *)(base + 4), HIST_NOTE, false); } /* advance base pointer past NUL */ bytes -= ++cp - base; diff --git a/lex.c b/lex.c index 137e39f..7839d90 100644 --- a/lex.c +++ b/lex.c @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.202 2015/07/05 13:49:42 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.203 2015/07/05 19:37:16 tg Exp $"); /* * states while lexing word @@ -1461,11 +1461,16 @@ getsc_line(Source *s) if (s->type == SFILE) shf_fdclose(s->u.shf); s->str = NULL; - } else if (interactive && *s->str && - (cur_prompt != PS1 || !ctype(*s->str, C_IFS | C_IFSWS))) { - histsave(&s->line, s->str, true, true); + } else if (interactive && *s->str) { + if (cur_prompt != PS1) + histsave(&s->line, s->str, HIST_APPEND, true); + else if (!ctype(*s->str, C_IFS | C_IFSWS)) + histsave(&s->line, s->str, HIST_QUEUE, true); #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY + else + goto check_for_sole_return; } else if (interactive && cur_prompt == PS1) { + check_for_sole_return: cp = Xstring(s->xs, xp); while (*cp && ctype(*cp, C_IFSWS)) ++cp; diff --git a/main.c b/main.c index 8bb4f0d..eecea60 100644 --- a/main.c +++ b/main.c @@ -34,7 +34,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/main.c,v 1.293 2015/04/29 20:07:33 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/main.c,v 1.294 2015/07/05 19:37:16 tg Exp $"); extern char **environ; @@ -803,6 +803,8 @@ shell(Source * volatile s, volatile bool toplevel) set_prompt(PS1, s); } t = compile(s, sfirst); + if (interactive) + histsave(&s->line, NULL, HIST_FLUSH, true); sfirst = false; if (!t) goto source_no_tree; diff --git a/mksh.1 b/mksh.1 index 268b463..fb9666b 100644 --- a/mksh.1 +++ b/mksh.1 @@ -1,4 +1,4 @@ -.\" $MirOS: src/bin/mksh/mksh.1,v 1.371 2015/07/05 17:50:40 tg Exp $ +.\" $MirOS: src/bin/mksh/mksh.1,v 1.372 2015/07/05 19:37:17 tg Exp $ .\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $ .\"- .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, @@ -1859,7 +1859,8 @@ below for more information. .It Ev HISTFILE The name of the file used to store command history. When assigned to or unset, the file is opened, history is truncated -then loaded from the file; subsequent new lines are appended. +then loaded from the file; subsequent new commands (possibly consisting +of several lines) are appended once they successfully compiled. Also, several invocations of the shell will share history if their .Ev HISTFILE parameters all point to the same file. diff --git a/sh.h b/sh.h index 5ab4d16..74d4b57 100644 --- a/sh.h +++ b/sh.h @@ -169,9 +169,9 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.732 2015/07/05 14:43:08 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.733 2015/07/05 19:37:18 tg Exp $"); #endif -#define MKSH_VERSION "R51 2015/06/28" +#define MKSH_VERSION "R51 2015/07/05" /* arithmetic types: C implementation */ #if !HAVE_CAN_INTTYPES @@ -1625,6 +1625,13 @@ EXTERN char **history; /* saved commands */ EXTERN char **histptr; /* last history item */ EXTERN mksh_ari_t histsize; /* history size */ +/* flags to histsave */ +#define HIST_FLUSH 0 +#define HIST_QUEUE 1 +#define HIST_APPEND 2 +#define HIST_STORE 3 +#define HIST_NOTE 4 + /* user and system time of last j_waitjed job */ EXTERN struct timeval j_usrtime, j_systime; @@ -1751,7 +1758,7 @@ void hist_init(Source *); #if HAVE_PERSISTENT_HISTORY void hist_finish(void); #endif -void histsave(int *, const char *, bool, bool); +void histsave(int *, const char *, int, bool); #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY bool histsync(void); #endif