[tcsh] Update to tcsh-6.18.00 - adapt tcsh-6.18.00-history-file-locking.patch

Vojtěch Vítek vvitek at fedoraproject.org
Wed Jun 6 12:12:04 UTC 2012


commit c6c5f0dcfe7ba392b99a799c5aefbdc3a3d88ef6
Author: Vojtech Vitek (V-Teq) <vvitek at redhat.com>
Date:   Wed Jun 6 14:08:07 2012 +0200

    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

 tcsh-6.18.00-history-file-locking.patch |  456 ++++++++++++++++++++++++-------
 tcsh.spec                               |    6 +-
 2 files changed, 358 insertions(+), 104 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 at 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 at 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
 
diff --git a/tcsh.spec b/tcsh.spec
index 04a13e3..2dfeede 100644
--- a/tcsh.spec
+++ b/tcsh.spec
@@ -14,9 +14,10 @@ Patch4: tcsh-6.15.00-hist-sub.patch
 Patch8: tcsh-6.14.00-syntax.patch
 Patch9: tcsh-6.13.00-memoryuse.patch
 Patch11: tcsh-6.14.00-order.patch
-# Proposed to upstream (http://bugs.gw.com/view.php?id=121)
+# Proposed upstream - http://github.com/tcsh-org/tcsh/pull/1
 Patch28: tcsh-6.17.00-manpage-spelling.patch
-Patch31: tcsh-6.17.00-history-file-locking.patch
+# Proposed upstream - http://github.com/tcsh-org/tcsh/pull/2
+Patch31: tcsh-6.18.00-history-file-locking.patch
 
 Provides: csh = %{version}
 Requires(post): grep
@@ -132,6 +133,7 @@ fi
   tcsh-6.17.00-status-pipeline-backquote-list-of-cmds.patch (reverted!)
 - Modify and adapt the existing patches to the new source code:
   tcsh-6.13.00-memoryuse.patch, tcsh-6.14.00-tinfo.patch,
+  tcsh-6.18.00-history-file-locking.patch
 
 * Thu Feb 16 2012 Vojtech Vitek (V-Teq) <vvitek at redhat.com> - 6.17-19
 - Handle pending signals before flush so that the the .history file


More information about the scm-commits mailing list