summaryrefslogtreecommitdiffstats
path: root/tcsh-6.18.00-history-file-locking.patch
diff options
context:
space:
mode:
authorVojtech Vitek (V-Teq) <vvitek@redhat.com>2012-06-06 14:08:07 +0200
committerVojtech Vitek (V-Teq) <vvitek@redhat.com>2012-06-06 14:08:07 +0200
commitc6c5f0dcfe7ba392b99a799c5aefbdc3a3d88ef6 (patch)
tree71fc5d8bd2a23fdc17f853035c3d3de04a32d2d4 /tcsh-6.18.00-history-file-locking.patch
parent8b0e83d044fc754ac8e04b7026005a5ce5c0c860 (diff)
downloadtcsh-rebase-6.19.00-c6c5f0dcfe7ba392b99a799c5aefbdc3a3d88ef6.tar.gz
tcsh-rebase-6.19.00-c6c5f0dcfe7ba392b99a799c5aefbdc3a3d88ef6.tar.xz
tcsh-rebase-6.19.00-c6c5f0dcfe7ba392b99a799c5aefbdc3a3d88ef6.zip
Update to tcsh-6.18.00 - adapt tcsh-6.18.00-history-file-locking.patch
Update the patch from http://github.com/VojtechVitek/tcsh/commit/e59f1ed7c4a23b7b72eb45b57909266e7c20a780
Diffstat (limited to 'tcsh-6.18.00-history-file-locking.patch')
-rw-r--r--tcsh-6.18.00-history-file-locking.patch456
1 files changed, 354 insertions, 102 deletions
diff --git a/tcsh-6.18.00-history-file-locking.patch b/tcsh-6.18.00-history-file-locking.patch
index 1df5f78..01b6102 100644
--- a/tcsh-6.18.00-history-file-locking.patch
+++ b/tcsh-6.18.00-history-file-locking.patch
@@ -1,27 +1,26 @@
-From d73747f08a9576f360e0e0b6c5f537547c30c5fa Mon Sep 17 00:00:00 2001
+From e59f1ed7c4a23b7b72eb45b57909266e7c20a780 Mon Sep 17 00:00:00 2001
From: "Vojtech Vitek (V-Teq)" <vvitek@redhat.com>
-Date: Thu, 15 Mar 2012 03:13:01 +0100
-Subject: [PATCH] Implement .history file locking - shared readers, exclusive
- writer
+Date: Wed, 16 May 2012 19:07:09 +0200
+Subject: [PATCH] Add .history file locking - shared readers, exclusive writer
Originally reported at Red Hat Bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=648592
Patch by Vojtech Vitek (V-Teq) <vvitek@redhat.com>
---
- sh.c | 91 ++++++++++++++++++++++++++++++++++++++++++++----------------
- sh.decls.h | 5 ++-
+ sh.c | 103 +++++++++++++++++++++++++++++++++--------------
+ sh.decls.h | 5 +-
sh.dir.c | 2 +-
sh.dol.c | 2 +-
- sh.err.c | 16 ++++++++++
- sh.h | 17 +++++++++++
- sh.hist.c | 62 +++++++++++++++++++++++------------------
+ sh.err.c | 16 +++++++
+ sh.h | 18 ++++++++
+ sh.hist.c | 131 ++++++++++++++++++++++++++++++------------------------------
sh.lex.c | 8 ++--
sh.sem.c | 2 +-
- 9 files changed, 145 insertions(+), 60 deletions(-)
+ 9 files changed, 183 insertions(+), 104 deletions(-)
diff --git a/sh.c b/sh.c
-index dcd9116..aaf32bc 100644
+index 77e75cb..febcad9 100644
--- a/sh.c
+++ b/sh.c
@@ -140,6 +140,7 @@ struct saved_state {
@@ -37,11 +36,29 @@ index dcd9116..aaf32bc 100644
* Source history before .login so that it is available in .login
*/
- loadhist(NULL, 0);
-+ loadhist(NULL, FD_RDLCK);
++ loadhist(NULL, HIST_FILE_RDLCK);
#ifndef LOGINFIRST
if (loginsh)
(void) srccat(varval(STRhome), STRsldotlogin);
-@@ -1522,20 +1523,52 @@ static int
+@@ -1492,7 +1493,7 @@ static int
+ srccat(Char *cp, Char *dp)
+ {
+ if (cp[0] == '/' && cp[1] == '\0')
+- return srcfile(short2str(dp), (mflag ? 0 : 1), 0, NULL);
++ return srcfile(short2str(dp), (mflag ? 0 : HIST_ONLY), 0, NULL);
+ else {
+ Char *ep;
+ char *ptr;
+@@ -1508,7 +1509,7 @@ srccat(Char *cp, Char *dp)
+ cleanup_push(ep, xfree);
+ ptr = short2str(ep);
+
+- rv = srcfile(ptr, (mflag ? 0 : 1), 0, NULL);
++ rv = srcfile(ptr, (mflag ? 0 : HIST_ONLY), 0, NULL);
+ cleanup_until(ep);
+ return rv;
+ }
+@@ -1522,20 +1523,49 @@ static int
#else
int
#endif /*WINNT_NATIVE*/
@@ -60,70 +77,85 @@ index dcd9116..aaf32bc 100644
- (void) close_on_exec(unit, 1);
- srcunit(unit, onlyown, flag, av);
- return 1;
-+ int *unit, copy;
++ int *unit;
+
+ unit = xmalloc(sizeof(*unit));
+ cleanup_push(unit, xfree);
+ *unit = xopen(f, O_LARGEFILE |
-+ ((flg & FD_WRLCK) ? (O_CREAT|O_RDWR) : O_RDONLY), 0600);
-+
-+ if (*unit == -1) {
-+ if (!bequiet)
-+ stderror(ERR_SYSTEM, f, strerror(errno));
-+ return -1;
-+ }
++ ((flg & HIST_FILE_WRLCK) ? (O_CREAT|O_RDWR) : O_RDONLY), 0600);
++ if (*unit == -1)
++ return 0; /* Error. */
+
+ cleanup_push(unit, open_cleanup);
+ *unit = dmove(*unit, -1);
+ (void) close_on_exec(*unit, 1);
-+ copy = *unit;
+
-+ if (flg & (FD_WRLCK | FD_RDLCK)) {
++ if (flg & (HIST_FILE_WRLCK | HIST_FILE_RDLCK)) {
+ struct flock fl;
+
-+ fl.l_type = (flg & FD_WRLCK) ? F_WRLCK : F_RDLCK;
++ fl.l_type = (flg & HIST_FILE_WRLCK) ? F_WRLCK : F_RDLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+
-+ if (fcntl(*unit, F_SETLKW, &fl) != -1)
-+ cleanup_push(unit, fcntl_cleanup);
++ cleanup_push(unit, fcntl_cleanup);
++ if (fcntl(*unit, F_SETLKW, &fl) == -1)
++ cleanup_ignore(unit);
+ }
+
-+ srcunit(copy, onlyown, (flg & (SRC_HFLAG | SRC_MFLAG)), av);
++ srcunit(*unit, onlyown, flg, av);
+
-+ /* Close the unit, if we don't want to leave it open & locked. */
-+ if ((flg & (FD_WRLCK | FD_RDLCK)) && (!(flg & FD_LEAVE_LCKD))) {
++ /* Unlock the unit, if we don't want to leave it locked (or open). */
++ if ((flg & (HIST_FILE_WRLCK | HIST_FILE_RDLCK)) &&
++ (!(flg & HIST_FILE_LOCK) || !(flg & HIST_FILE_OPEN)))
+ cleanup_until(unit); /* fcntl_cleanup */
-+ if (!(flg & FD_LEAVE_OPEN)) {
-+ cleanup_until(unit); /* open_cleanup */
-+ cleanup_until(unit); /* xfree */
-+ }
+
-+ return -1; /* Invalid file descriptor. */
++ /* Close the unit, if we don't want to leave it open. */
++ if (!(flg & HIST_FILE_OPEN)) {
++ cleanup_until(unit); /* open_cleanup */
++ cleanup_until(unit); /* xfree */
++ return -1; /* Not error but invalid file descriptor. */
+ }
+
-+ return *unit;
++ return *unit; /* File descriptor (fd > FSAFE). */
}
-@@ -1593,10 +1626,14 @@ st_save(struct saved_state *st, int unit, int hflg, Char **al, Char **av)
+@@ -1544,7 +1574,7 @@ srcfile(const char *f, int onlyown, int flag, Char **av)
+ * fd.
+ */
+ static void
+-st_save(struct saved_state *st, int unit, int hflg, Char **al, Char **av)
++st_save(struct saved_state *st, int unit, int flg, Char **al, Char **av)
+ {
+ st->insource = insource;
+ st->SHIN = SHIN;
+@@ -1593,10 +1623,14 @@ st_save(struct saved_state *st, int unit, int hflg, Char **al, Char **av)
st->onelflg = onelflg;
st->enterhist = enterhist;
st->justpr = justpr;
- if (hflg)
-+ if (hflg && SRC_HFLAG)
++ if (flg & (HIST_ONLY | HIST_MERGE))
st->HIST = HIST;
else
st->HIST = '\0';
-+ if (hflg && FD_LEAVE_OPEN)
++ if (flg & HIST_FILE_OPEN)
+ st->close_unit = 0;
+ else
+ st->close_unit = 1;
st->cantell = cantell;
cpybin(st->B, B);
-@@ -1668,7 +1705,8 @@ st_restore(void *xst)
+@@ -1635,7 +1669,7 @@ st_save(struct saved_state *st, int unit, int hflg, Char **al, Char **av)
+ evalp = 0;
+ alvec = al;
+ alvecp = 0;
+- enterhist = hflg;
++ enterhist = flg & (HIST_ONLY | HIST_MERGE);
+ if (enterhist)
+ HIST = '\0';
+ insource = 1;
+@@ -1668,7 +1702,8 @@ st_restore(void *xst)
}
cpybin(B, st->B);
@@ -133,7 +165,25 @@ index dcd9116..aaf32bc 100644
insource = st->insource;
SHIN = st->SHIN;
-@@ -2153,24 +2191,25 @@ process(int catch)
+@@ -1704,7 +1739,7 @@ st_restore(void *xst)
+ * we don't chance it. This occurs on ".cshrc"s and the like.
+ */
+ static void
+-srcunit(int unit, int onlyown, int hflg, Char **av)
++srcunit(int unit, int onlyown, int flg, Char **av)
+ {
+ struct saved_state st;
+
+@@ -1730,7 +1765,7 @@ srcunit(int unit, int onlyown, int hflg, Char **av)
+ }
+
+ /* Save the current state and move us to a new state */
+- st_save(&st, unit, hflg, NULL, av);
++ st_save(&st, unit, flg, NULL, av);
+
+ /*
+ * Now if we are allowing commands to be interrupted, we let ourselves be
+@@ -2153,24 +2188,25 @@ process(int catch)
}
/*ARGSUSED*/
@@ -146,7 +196,7 @@ index dcd9116..aaf32bc 100644
- int hflg = 0;
char *file;
+ int fd;
-+ int hflg = 0;
++ int newflg = 0;
USE(c);
t++;
@@ -154,35 +204,38 @@ index dcd9116..aaf32bc 100644
if (*++t == NULL)
stderror(ERR_NAME | ERR_HFLAG);
- hflg++;
-+ hflg |= SRC_HFLAG;
++ newflg |= HIST_ONLY;
}
else if (*t && eq(*t, STRmm)) {
if (*++t == NULL)
stderror(ERR_NAME | ERR_MFLAG);
- hflg = 2;
-+ hflg |= SRC_MFLAG;
++ newflg |= HIST_MERGE;
}
f = globone(*t++, G_ERROR);
-@@ -2178,9 +2217,13 @@ dosource(Char **t, struct command *c)
+@@ -2178,9 +2214,16 @@ dosource(Char **t, struct command *c)
cleanup_push(file, xfree);
xfree(f);
t = glob_all_or_error(t);
- if ((!srcfile(file, 0, hflg, t)) && (!hflg) && (!bequiet))
- stderror(ERR_SYSTEM, file, strerror(errno));
- cleanup_until(file);
-+ fd = srcfile(file, 0, (hflg | flg), t);
++ fd = srcfile(file, 0, (flg | newflg), t);
++ if ((!fd) && (!newflg) && (!bequiet))
++ stderror(ERR_SYSTEM, f, strerror(errno));
+
-+ /* Postpone fd cleanup, which is on the top of cleaning stack. */
++ /* We need to preserve fd and it's cleaning routines on the top of the
++ * cleaning stack. Don't call cleanup_until() but clean it manually. */
+ cleanup_ignore(file);
+ xfree(file);
+
-+ return fd; /* File descriptor or -1. */
++ return fd; /* Valid/invalid file descriptor (>FSAVE, -1). Zero on error. */
}
/*
diff --git a/sh.decls.h b/sh.decls.h
-index db90288..d4332f3 100644
+index cd13288..d45c599 100644
--- a/sh.decls.h
+++ b/sh.decls.h
@@ -37,7 +37,7 @@
@@ -212,7 +265,7 @@ index db90288..d4332f3 100644
/*
diff --git a/sh.dir.c b/sh.dir.c
-index ab89855..4bfe430 100644
+index 058bc27..cf3b349 100644
--- a/sh.dir.c
+++ b/sh.dir.c
@@ -1342,7 +1342,7 @@ loaddirs(Char *fname)
@@ -225,7 +278,7 @@ index ab89855..4bfe430 100644
}
diff --git a/sh.dol.c b/sh.dol.c
-index 45b10e0..02dfe98 100644
+index 5df8c60..7db7b60 100644
--- a/sh.dol.c
+++ b/sh.dol.c
@@ -1110,6 +1110,6 @@ again:
@@ -237,7 +290,7 @@ index 45b10e0..02dfe98 100644
cleanup_until(&inheredoc);
}
diff --git a/sh.err.c b/sh.err.c
-index e157d6a..29d41c3 100644
+index d8574cd..85093fa 100644
--- a/sh.err.c
+++ b/sh.err.c
@@ -514,6 +514,22 @@ open_cleanup(void *xptr)
@@ -264,47 +317,221 @@ index e157d6a..29d41c3 100644
{
DIR *dir;
diff --git a/sh.h b/sh.h
-index 691add3..558b093 100644
+index 88f7e90..1d13322 100644
--- a/sh.h
+++ b/sh.h
-@@ -50,6 +50,23 @@
+@@ -50,6 +50,24 @@
# include <inttypes.h>
#endif
+#include <unistd.h>
+#include <fcntl.h>
++
+/*
-+ * Source flags (representing -h or -m).
-+ *
-+ * File locking flags.
-+ * - shared and exclusive (read and write) access to a file
-+ * - currently used in sh.c and sh.hist.c files while acessing
-+ * ~/.history file only.
++ * History flags.
+ */
-+#define SRC_HFLAG 0x01 /* History flag */
-+#define SRC_MFLAG 0x02 /* Merge flag */
-+#define FD_WRLCK 0x04 /* Write lock */
-+#define FD_RDLCK 0x08 /* Read lock */
-+#define FD_LEAVE_OPEN 0x10 /* Leave file open */
-+#define FD_LEAVE_LCKD 0x20 /* Leave file locked */
++#define HIST_ONLY 0x001
++#define HIST_SAVE 0x002
++#define HIST_LOAD 0x004
++#define HIST_REV 0x008
++#define HIST_CLEAR 0x010
++#define HIST_MERGE 0x020
++#define HIST_TIME 0x040
++#define HIST_FILE_WRLCK 0x080 /* Write lock */
++#define HIST_FILE_RDLCK 0x100 /* Read lock */
++#define HIST_FILE_OPEN 0x200 /* Leave file open */
++#define HIST_FILE_LOCK 0x400 /* Leave file locked */
+
#if !defined(HAVE_STDINT_H) && !defined(HAVE_INTTYPES_H) && !defined(WINNT_NATIVE)
typedef unsigned long intptr_t;
#endif
diff --git a/sh.hist.c b/sh.hist.c
-index 6a12737..7df84e5 100644
+index 2482a13..4b4aa10 100644
--- a/sh.hist.c
+++ b/sh.hist.c
-@@ -1173,7 +1173,7 @@ dohist(Char **vp, struct command *c)
+@@ -44,14 +44,6 @@ Char HistLit = 0;
+ static int heq (const struct wordent *, const struct wordent *);
+ static void hfree (struct Hist *);
+
+-#define HIST_ONLY 0x01
+-#define HIST_SAVE 0x02
+-#define HIST_LOAD 0x04
+-#define HIST_REV 0x08
+-#define HIST_CLEAR 0x10
+-#define HIST_MERGE 0x20
+-#define HIST_TIME 0x40
+-
+ /*
+ * C shell
+ */
+@@ -143,7 +135,7 @@ discardExcess(int histlen)
+ void
+ savehist(
+ struct wordent *sp,
+- int mflg) /* true if -m (merge) specified */
++ int flg)
+ {
+ int histlen = 0;
+ Char *cp;
+@@ -160,7 +152,7 @@ savehist(
+ histlen = histlen * 10 + *cp++ - '0';
+ }
+ if (sp)
+- (void) enthist(++eventno, sp, 1, mflg, histlen);
++ (void) enthist(++eventno, sp, 1, flg, histlen);
+ discardExcess(histlen);
+ }
+
+@@ -933,7 +925,7 @@ enthist(
+ int event, /* newly incremented global eventno */
+ struct wordent *lp,
+ int docopy,
+- int mflg, /* true if merge requested */
++ int flg,
+ int histlen) /* -1 if unknown */
+ {
+ struct Hist *p = NULL, *pp = &Histlist, *pTime = NULL;
+@@ -953,7 +945,7 @@ enthist(
+ Htime = p->Htime;
+ /* If we are merging, and the old entry is at the place we want
+ * to insert the new entry, then remember the place. */
+- if (mflg && Htime != 0 && p->Hprev->Htime >= Htime)
++ if ((flg & HIST_MERGE) && Htime != 0 && p->Hprev->Htime >= Htime)
+ pTime = p->Hprev;
+ if (!fastMergeErase)
+ renumberHist(p); /* Reset Href of subsequent entries */
+@@ -1012,7 +1004,7 @@ enthist(
+ /* The head of history list is the default insertion point.
+ If merging, advance insertion point, in pp, according to Htime. */
+ /* XXX -- In histdup=all, Htime values can be non-monotonic. */
+- if (mflg) { /* merge according to np->Htime */
++ if (flg & HIST_MERGE) { /* merge according to np->Htime */
+ pp = mergeInsertionPoint(np, pTime);
+ for (p = pp->Hnext; p && p->Htime == np->Htime; pp = p, p = p->Hnext) {
+ if (heq(&p->Hlex, &np->Hlex)) {
+@@ -1051,9 +1043,9 @@ hfree(struct Hist *hp)
+ }
+
+ PG_STATIC void
+-phist(struct Hist *hp, int hflg)
++phist(struct Hist *hp, int flg)
+ {
+- if (hflg & HIST_ONLY) {
++ if (flg & HIST_ONLY) {
+ int old_output_raw;
+
+ /*
+@@ -1065,7 +1057,7 @@ phist(struct Hist *hp, int hflg)
+ old_output_raw = output_raw;
+ output_raw = 1;
+ cleanup_push(&old_output_raw, output_raw_restore);
+- if (hflg & HIST_TIME)
++ if (flg & HIST_TIME)
+ /*
+ * Make file entry with history time in format:
+ * "+NNNNNNNNNN" (10 digits, left padded with ascii '0')
+@@ -1096,7 +1088,7 @@ phist(struct Hist *hp, int hflg)
+ }
+
+ PG_STATIC void
+-dophist(int n, int hflg)
++dophist(int n, int flg)
+ {
+ struct Hist *hp;
+ if (setintr) {
+@@ -1105,7 +1097,7 @@ dophist(int n, int hflg)
+ pintr_push_enable(&old_pintr_disabled);
+ cleanup_until(&old_pintr_disabled);
+ }
+- if ((hflg & HIST_REV) == 0) {
++ if (!(flg & HIST_REV)) {
+ /* Since the history list is stored most recent first, non-reversing
+ * print needs to print (backwards) up the list. */
+ if ((unsigned)n >= histCount)
+@@ -1119,10 +1111,10 @@ dophist(int n, int hflg)
+ if (hp == NULL)
+ return; /* nothing to print */
+ for (; hp != &Histlist; hp = hp->Hprev)
+- phist(hp, hflg);
++ phist(hp, flg);
+ } else {
+ for (hp = Histlist.Hnext; n-- > 0 && hp != NULL; hp = hp->Hnext)
+- phist(hp, hflg);
++ phist(hp, flg);
+ }
+ }
+
+@@ -1130,7 +1122,7 @@ dophist(int n, int hflg)
+ void
+ dohist(Char **vp, struct command *c)
+ {
+- int n, hflg = 0;
++ int n, flg = 0;
+
+ USE(c);
+ if (getn(varval(STRhistory)) == 0)
+@@ -1141,40 +1133,40 @@ dohist(Char **vp, struct command *c)
+ while (*++vp2)
+ switch (*vp2) {
+ case 'c':
+- hflg |= HIST_CLEAR;
++ flg |= HIST_CLEAR;
+ break;
+ case 'h':
+- hflg |= HIST_ONLY;
++ flg |= HIST_ONLY;
+ break;
+ case 'r':
+- hflg |= HIST_REV;
++ flg |= HIST_REV;
+ break;
+ case 'S':
+- hflg |= HIST_SAVE;
++ flg |= HIST_SAVE;
+ break;
+ case 'L':
+- hflg |= HIST_LOAD;
++ flg |= HIST_LOAD;
+ break;
+ case 'M':
+- hflg |= HIST_MERGE;
++ flg |= HIST_MERGE;
+ break;
+ case 'T':
+- hflg |= HIST_TIME;
++ flg |= HIST_TIME;
+ break;
+ default:
+ stderror(ERR_HISTUS, "chrSLMT");
+ break;
+ }
+ }
+- if (hflg & HIST_CLEAR) {
++ if (flg & HIST_CLEAR) {
+ struct Hist *np, *hp;
+ for (hp = &Histlist; (np = hp->Hnext) != NULL;)
+ hremove(np), hfree(np);
}
- if (hflg & (HIST_LOAD | HIST_MERGE))
+- if (hflg & (HIST_LOAD | HIST_MERGE))
- loadhist(*vp, (hflg & HIST_MERGE) ? 1 : 0);
-+ loadhist(*vp, ((hflg & HIST_MERGE) ? SRC_MFLAG : 0) | FD_RDLCK);
- else if (hflg & HIST_SAVE)
+- else if (hflg & HIST_SAVE)
++ if (flg & (HIST_LOAD | HIST_MERGE))
++ loadhist(*vp, (flg | HIST_FILE_RDLCK));
++ else if (flg & HIST_SAVE)
rechist(*vp, 1);
else {
-@@ -1224,8 +1224,8 @@ fmthist(int fmt, ptr_t ptr)
+ if (*vp)
+@@ -1182,7 +1174,7 @@ dohist(Char **vp, struct command *c)
+ else {
+ n = getn(varval(STRhistory));
+ }
+- dophist(n, hflg);
++ dophist(n, flg);
+ }
+ }
+
+@@ -1224,8 +1216,8 @@ fmthist(int fmt, ptr_t ptr)
void
rechist(Char *fname, int ref)
{
@@ -315,15 +542,7 @@ index 6a12737..7df84e5 100644
struct varent *shist;
static Char *dumphist[] = {STRhistory, STRmhT, 0, 0};
-@@ -1239,7 +1239,6 @@ rechist(Char *fname, int ref)
- ((snum = varval(STRhistory)) == STRNULL))
- snum = STRmaxint;
-
--
- if (fname == NULL) {
- if ((fname = varval(STRhistfile)) == STRNULL)
- fname = Strspl(varval(STRhome), &STRtildothist[1]);
-@@ -1255,15 +1254,12 @@ rechist(Char *fname, int ref)
+@@ -1255,15 +1247,12 @@ rechist(Char *fname, int ref)
* with numerous shells being in simultaneous use. Imagine
* any kind of window system. All these shells 'share' the same
* ~/.history file for recording their command line history.
@@ -344,7 +563,7 @@ index 6a12737..7df84e5 100644
/*
* We need the didfds stuff before loadhist otherwise
* exec in a script will fail to print if merge is set.
-@@ -1271,22 +1267,34 @@ rechist(Char *fname, int ref)
+@@ -1271,32 +1260,42 @@ rechist(Char *fname, int ref)
*/
oldidfds = didfds;
didfds = 0;
@@ -357,31 +576,22 @@ index 6a12737..7df84e5 100644
- if (fp == -1) {
- didfds = oldidfds;
- return;
-+ if ((shist = adrof(STRsavehist)) != NULL && shist->vec != NULL
-+ && shist->vec[1] && eq(shist->vec[1], STRmerge)) {
++ if (((shist = adrof(STRsavehist)) != NULL && shist->vec != NULL) &&
++ (shist->vec[1] && eq(shist->vec[1], STRmerge))) {
+ /* Read .history file, leave it's fd open for writing. */
-+ fd = loadhist(fname, SRC_MFLAG|FD_WRLCK|FD_LEAVE_OPEN|FD_LEAVE_LCKD);
-+ if (fd != -1) {
++ fd = loadhist(fname, HIST_MERGE|HIST_FILE_WRLCK|HIST_FILE_OPEN|HIST_FILE_LOCK);
++ if (fd > 0) {
+ /* Truncate the .history file. */
+ (void) ftruncate(fd, 0);
+ (void) lseek(fd, 0, SEEK_SET);
+ }
- }
-- ftmp = SHOUT;
-- SHOUT = fp;
-- dumphist[2] = snum;
-- dohist(dumphist, NULL);
-- xclose(fp);
-- SHOUT = ftmp;
-+
-+ /* Open .history file for writing (if not open yet). */
-+ if (fd == -1) {
++ }
++ if (fd <= 0) {
++ /* Open .history file for writing (if not open yet). */
+ fd = xopen(short2str(fname), O_LARGEFILE|O_CREAT|O_WRONLY|O_TRUNC, 0600);
-+ cleanup_until(fname);
+ if (fd != -1)
+ cleanup_push(&fd, open_cleanup);
+ }
-+
+ if (fd != -1) {
+ ftmp = SHOUT;
+ SHOUT = fd;
@@ -389,13 +599,55 @@ index 6a12737..7df84e5 100644
+ /* Write history to the .history file. */
+ dohist(dumphist, NULL);
+ SHOUT = ftmp;
-+ }
-+
+ }
+- ftmp = SHOUT;
+- SHOUT = fp;
+- dumphist[2] = snum;
+- dohist(dumphist, NULL);
+- xclose(fp);
+- SHOUT = ftmp;
didfds = oldidfds;
++ cleanup_until(fname);
}
+
+ /* This is the entry point for loading history data from a file. */
+-void
+-loadhist(Char *fname, int mflg)
++int
++loadhist(Char *fname, int flg)
+ {
+ static Char *loadhist_cmd[] = {STRsource, NULL, NULL, NULL};
+- loadhist_cmd[1] = mflg ? STRmm : STRmh;
++ int fd;
++ loadhist_cmd[1] = (flg & HIST_MERGE) ? STRmm : STRmh;
+
+ if (fname != NULL)
+ loadhist_cmd[2] = fname;
+@@ -1305,15 +1304,17 @@ loadhist(Char *fname, int mflg)
+ else
+ loadhist_cmd[2] = STRtildothist;
+
+- dosource(loadhist_cmd, NULL);
++ fd = dosource(loadhist_cmd, NULL, flg);
+
+- /* During history merging (enthist sees mflg set), we disable management of
+- * Hnum and Href (because fastMergeErase is true). So now reset all the
++ /* During history merging (enthist sees merge flag), we disable management
++ * of Hnum and Href (because fastMergeErase is true). So now reset all the
+ * values based on the final ordering of the history list. */
+- if (mflg) {
++ if (flg & HIST_MERGE) {
+ int n = eventno;
+ struct Hist *hp = &Histlist;
+ while ((hp = hp->Hnext))
+ hp->Hnum = hp->Href = n--;
+ }
++
++ return fd; /* Valid/invalid file descriptor (>FSAVE, -1). Zero on error. */
+ }
diff --git a/sh.lex.c b/sh.lex.c
-index 80643f7..e128789 100644
+index 08520dd..a87559d 100644
--- a/sh.lex.c
+++ b/sh.lex.c
@@ -1595,7 +1595,7 @@ wide_read(int fildes, Char *buf, size_t nchars, int use_fclens)
@@ -435,7 +687,7 @@ index 80643f7..e128789 100644
fbuf = xcalloc(2, sizeof(Char **));
fblocks = 1;
diff --git a/sh.sem.c b/sh.sem.c
-index c880974..765bf50 100644
+index 99cd83c..92bef5d 100644
--- a/sh.sem.c
+++ b/sh.sem.c
@@ -892,7 +892,7 @@ doio(struct command *t, int *pipein, int *pipeout)
@@ -448,5 +700,5 @@ index c880974..765bf50 100644
}
else
--
-1.7.6.5
+1.7.7.6