when using persistent history (and not MKSH_SMALL), let the shells
concurrently accessing the same $HISTFILE be more synchronised with each other: empty lines (just pressing Return) and duplicates (that are split and written twice by the lines loaded from $HISTFILE in the meantime); requested by Maximilian “mxey” Gaß in #!/bin/mksh
This commit is contained in:
parent
f3b3b4b1fb
commit
2765a07564
65
histrap.c
65
histrap.c
@ -2,7 +2,7 @@
|
||||
/* $OpenBSD: trap.c,v 1.22 2005/03/30 17:16:37 deraadt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
* Thorsten Glaser <tg@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
@ -26,7 +26,7 @@
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.90 2009/12/12 22:27:08 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.91 2010/01/25 16:12:55 tg Exp $");
|
||||
|
||||
/*-
|
||||
* MirOS: This is the default mapping type, and need not be specified.
|
||||
@ -51,7 +51,7 @@ static int sprinkle(int);
|
||||
|
||||
static int hist_execute(char *);
|
||||
static int hist_replace(char **, const char *, const char *, int);
|
||||
static char **hist_get(const char *, int, int);
|
||||
static char **hist_get(const char *, bool, bool);
|
||||
static char **hist_get_oldest(void);
|
||||
static void histbackup(void);
|
||||
|
||||
@ -368,7 +368,7 @@ hist_replace(char **hp, const char *pat, const char *rep, int globr)
|
||||
* pattern is a number or string
|
||||
*/
|
||||
static char **
|
||||
hist_get(const char *str, int approx, int allow_cur)
|
||||
hist_get(const char *str, bool approx, bool allow_cur)
|
||||
{
|
||||
char **hp = NULL;
|
||||
int n;
|
||||
@ -407,7 +407,7 @@ hist_get(const char *str, int approx, int allow_cur)
|
||||
|
||||
/* Return a pointer to the newest command in the history */
|
||||
char **
|
||||
hist_get_newest(int allow_cur)
|
||||
hist_get_newest(bool allow_cur)
|
||||
{
|
||||
if (histptr < history || (!allow_cur && histptr == history)) {
|
||||
bi_errorf("no history (yet)");
|
||||
@ -592,6 +592,27 @@ init_histvec(void)
|
||||
* It turns out that there is a lot of ghastly hackery here
|
||||
*/
|
||||
|
||||
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
||||
/* do not save command in history but possibly sync */
|
||||
bool
|
||||
histsync(void)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (histfd) {
|
||||
int lno = hist_source->line;
|
||||
|
||||
hist_source->line++;
|
||||
writehistfile(0, NULL);
|
||||
hist_source->line--;
|
||||
|
||||
if (lno != hist_source->line)
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return (changed);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* save command in history
|
||||
@ -606,7 +627,11 @@ histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
|
||||
if ((cp = strchr(c, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
|
||||
if (ignoredups && !strcmp(c, *histptr)) {
|
||||
if (ignoredups && !strcmp(c, *histptr)
|
||||
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
||||
&& !histsync()
|
||||
#endif
|
||||
) {
|
||||
afree(c, APERM);
|
||||
return;
|
||||
}
|
||||
@ -962,19 +987,21 @@ writehistfile(int lno, char *cmd)
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* we can write our bit now
|
||||
*/
|
||||
hdr[0] = COMMAND;
|
||||
hdr[1] = (lno>>24)&0xff;
|
||||
hdr[2] = (lno>>16)&0xff;
|
||||
hdr[3] = (lno>>8)&0xff;
|
||||
hdr[4] = lno&0xff;
|
||||
bytes = strlen(cmd) + 1;
|
||||
if ((write(histfd, hdr, 5) != 5) ||
|
||||
(write(histfd, cmd, bytes) != bytes))
|
||||
goto bad;
|
||||
hsize = lseek(histfd, (off_t)0, SEEK_END);
|
||||
if (cmd) {
|
||||
/*
|
||||
* we can write our bit now
|
||||
*/
|
||||
hdr[0] = COMMAND;
|
||||
hdr[1] = (lno>>24)&0xff;
|
||||
hdr[2] = (lno>>16)&0xff;
|
||||
hdr[3] = (lno>>8)&0xff;
|
||||
hdr[4] = lno&0xff;
|
||||
bytes = strlen(cmd) + 1;
|
||||
if ((write(histfd, hdr, 5) != 5) ||
|
||||
(write(histfd, cmd, bytes) != bytes))
|
||||
goto bad;
|
||||
hsize = lseek(histfd, (off_t)0, SEEK_END);
|
||||
}
|
||||
(void)flock(histfd, LOCK_UN);
|
||||
return;
|
||||
bad:
|
||||
|
15
lex.c
15
lex.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.103 2009/12/05 20:17:59 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.104 2010/01/25 16:12:56 tg Exp $");
|
||||
|
||||
/*
|
||||
* states while lexing word
|
||||
@ -1321,7 +1321,7 @@ static void
|
||||
getsc_line(Source *s)
|
||||
{
|
||||
char *xp = Xstring(s->xs, xp), *cp;
|
||||
int interactive = Flag(FTALKING) && s->type == SSTDIN;
|
||||
bool interactive = Flag(FTALKING) && s->type == SSTDIN;
|
||||
int have_tty = interactive && (s->flags & SF_TTY);
|
||||
|
||||
/* Done here to ensure nothing odd happens when a timeout occurs */
|
||||
@ -1413,8 +1413,17 @@ getsc_line(Source *s)
|
||||
shf_fdclose(s->u.shf);
|
||||
s->str = NULL;
|
||||
} else if (interactive && *s->str &&
|
||||
(cur_prompt != PS1 || !ctype(*s->str, C_IFS | C_IFSWS)))
|
||||
(cur_prompt != PS1 || !ctype(*s->str, C_IFS | C_IFSWS))) {
|
||||
histsave(&s->line, s->str, true, true);
|
||||
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
||||
} else if (interactive && cur_prompt == PS1) {
|
||||
cp = Xstring(s->xs, xp);
|
||||
while (*cp && ctype(*cp, C_IFSWS))
|
||||
++cp;
|
||||
if (!*cp)
|
||||
histsync();
|
||||
#endif
|
||||
}
|
||||
if (interactive)
|
||||
set_prompt(PS2, NULL);
|
||||
}
|
||||
|
5
mksh.1
5
mksh.1
@ -1,4 +1,4 @@
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.208 2010/01/25 14:25:15 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.209 2010/01/25 16:12:56 tg Exp $
|
||||
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
|
||||
.\"-
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
@ -1727,8 +1727,7 @@ below for more information.
|
||||
.It Ev HISTFILE
|
||||
The name of the file used to store command history.
|
||||
When assigned to, history is loaded from the specified file.
|
||||
Also, several invocations of the shell
|
||||
running on the same machine will share history if their
|
||||
Also, several invocations of the shell will share history if their
|
||||
.Ev HISTFILE
|
||||
parameters all point to the same file.
|
||||
.Pp
|
||||
|
7
sh.h
7
sh.h
@ -148,7 +148,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.375 2010/01/25 14:38:03 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.376 2010/01/25 16:12:57 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R39 2010/01/08"
|
||||
|
||||
@ -1432,6 +1432,9 @@ void hist_init(Source *);
|
||||
void hist_finish(void);
|
||||
#endif
|
||||
void histsave(int *, const char *, bool, bool);
|
||||
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
||||
bool histsync(void);
|
||||
#endif
|
||||
int c_fc(const char **);
|
||||
void sethistsize(int);
|
||||
#if HAVE_PERSISTENT_HISTORY
|
||||
@ -1441,7 +1444,7 @@ char **histpos(void);
|
||||
int histnum(int);
|
||||
int findhist(int, int, const char *, int);
|
||||
int findhistrel(const char *);
|
||||
char **hist_get_newest(int);
|
||||
char **hist_get_newest(bool);
|
||||
void inittraps(void);
|
||||
void alarm_init(void);
|
||||
Trap *gettrap(const char *, int);
|
||||
|
Loading…
x
Reference in New Issue
Block a user