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 $ */
|
/* $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>
|
* Thorsten Glaser <tg@mirbsd.org>
|
||||||
*
|
*
|
||||||
* Provided that these terms and disclaimer and all copyright notices
|
* Provided that these terms and disclaimer and all copyright notices
|
||||||
@ -26,7 +26,7 @@
|
|||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#endif
|
#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.
|
* 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_execute(char *);
|
||||||
static int hist_replace(char **, const char *, const char *, int);
|
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 char **hist_get_oldest(void);
|
||||||
static void histbackup(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
|
* pattern is a number or string
|
||||||
*/
|
*/
|
||||||
static char **
|
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;
|
char **hp = NULL;
|
||||||
int n;
|
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 */
|
/* Return a pointer to the newest command in the history */
|
||||||
char **
|
char **
|
||||||
hist_get_newest(int allow_cur)
|
hist_get_newest(bool allow_cur)
|
||||||
{
|
{
|
||||||
if (histptr < history || (!allow_cur && histptr == history)) {
|
if (histptr < history || (!allow_cur && histptr == history)) {
|
||||||
bi_errorf("no history (yet)");
|
bi_errorf("no history (yet)");
|
||||||
@ -592,6 +592,27 @@ init_histvec(void)
|
|||||||
* It turns out that there is a lot of ghastly hackery here
|
* 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
|
* 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)
|
if ((cp = strchr(c, '\n')) != NULL)
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
|
|
||||||
if (ignoredups && !strcmp(c, *histptr)) {
|
if (ignoredups && !strcmp(c, *histptr)
|
||||||
|
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
||||||
|
&& !histsync()
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
afree(c, APERM);
|
afree(c, APERM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -962,19 +987,21 @@ writehistfile(int lno, char *cmd)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
if (cmd) {
|
||||||
* we can write our bit now
|
/*
|
||||||
*/
|
* we can write our bit now
|
||||||
hdr[0] = COMMAND;
|
*/
|
||||||
hdr[1] = (lno>>24)&0xff;
|
hdr[0] = COMMAND;
|
||||||
hdr[2] = (lno>>16)&0xff;
|
hdr[1] = (lno>>24)&0xff;
|
||||||
hdr[3] = (lno>>8)&0xff;
|
hdr[2] = (lno>>16)&0xff;
|
||||||
hdr[4] = lno&0xff;
|
hdr[3] = (lno>>8)&0xff;
|
||||||
bytes = strlen(cmd) + 1;
|
hdr[4] = lno&0xff;
|
||||||
if ((write(histfd, hdr, 5) != 5) ||
|
bytes = strlen(cmd) + 1;
|
||||||
(write(histfd, cmd, bytes) != bytes))
|
if ((write(histfd, hdr, 5) != 5) ||
|
||||||
goto bad;
|
(write(histfd, cmd, bytes) != bytes))
|
||||||
hsize = lseek(histfd, (off_t)0, SEEK_END);
|
goto bad;
|
||||||
|
hsize = lseek(histfd, (off_t)0, SEEK_END);
|
||||||
|
}
|
||||||
(void)flock(histfd, LOCK_UN);
|
(void)flock(histfd, LOCK_UN);
|
||||||
return;
|
return;
|
||||||
bad:
|
bad:
|
||||||
|
15
lex.c
15
lex.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#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
|
* states while lexing word
|
||||||
@ -1321,7 +1321,7 @@ static void
|
|||||||
getsc_line(Source *s)
|
getsc_line(Source *s)
|
||||||
{
|
{
|
||||||
char *xp = Xstring(s->xs, xp), *cp;
|
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);
|
int have_tty = interactive && (s->flags & SF_TTY);
|
||||||
|
|
||||||
/* Done here to ensure nothing odd happens when a timeout occurs */
|
/* Done here to ensure nothing odd happens when a timeout occurs */
|
||||||
@ -1413,8 +1413,17 @@ getsc_line(Source *s)
|
|||||||
shf_fdclose(s->u.shf);
|
shf_fdclose(s->u.shf);
|
||||||
s->str = NULL;
|
s->str = NULL;
|
||||||
} else if (interactive && *s->str &&
|
} 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);
|
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)
|
if (interactive)
|
||||||
set_prompt(PS2, NULL);
|
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 $
|
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
|
||||||
.\"-
|
.\"-
|
||||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||||
@ -1727,8 +1727,7 @@ below for more information.
|
|||||||
.It Ev HISTFILE
|
.It Ev HISTFILE
|
||||||
The name of the file used to store command history.
|
The name of the file used to store command history.
|
||||||
When assigned to, history is loaded from the specified file.
|
When assigned to, history is loaded from the specified file.
|
||||||
Also, several invocations of the shell
|
Also, several invocations of the shell will share history if their
|
||||||
running on the same machine will share history if their
|
|
||||||
.Ev HISTFILE
|
.Ev HISTFILE
|
||||||
parameters all point to the same file.
|
parameters all point to the same file.
|
||||||
.Pp
|
.Pp
|
||||||
|
7
sh.h
7
sh.h
@ -148,7 +148,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXTERN
|
#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
|
#endif
|
||||||
#define MKSH_VERSION "R39 2010/01/08"
|
#define MKSH_VERSION "R39 2010/01/08"
|
||||||
|
|
||||||
@ -1432,6 +1432,9 @@ void hist_init(Source *);
|
|||||||
void hist_finish(void);
|
void hist_finish(void);
|
||||||
#endif
|
#endif
|
||||||
void histsave(int *, const char *, bool, bool);
|
void histsave(int *, const char *, bool, bool);
|
||||||
|
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
||||||
|
bool histsync(void);
|
||||||
|
#endif
|
||||||
int c_fc(const char **);
|
int c_fc(const char **);
|
||||||
void sethistsize(int);
|
void sethistsize(int);
|
||||||
#if HAVE_PERSISTENT_HISTORY
|
#if HAVE_PERSISTENT_HISTORY
|
||||||
@ -1441,7 +1444,7 @@ char **histpos(void);
|
|||||||
int histnum(int);
|
int histnum(int);
|
||||||
int findhist(int, int, const char *, int);
|
int findhist(int, int, const char *, int);
|
||||||
int findhistrel(const char *);
|
int findhistrel(const char *);
|
||||||
char **hist_get_newest(int);
|
char **hist_get_newest(bool);
|
||||||
void inittraps(void);
|
void inittraps(void);
|
||||||
void alarm_init(void);
|
void alarm_init(void);
|
||||||
Trap *gettrap(const char *, int);
|
Trap *gettrap(const char *, int);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user