bin/66420: [PATCH] tcsh: history mangles command lines containing the hash character

Oliver Eikemeier eik at FreeBSD.org
Sun May 9 07:20:25 PDT 2004


>Number:         66420
>Category:       bin
>Synopsis:       [PATCH] tcsh: history mangles command lines containing the hash character
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun May 09 07:20:24 PDT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Oliver Eikemeier
>Release:        FreeBSD 4.10-STABLE i386
>Organization:
Fillmore Labs - http://www.fillmore-labs.com
>Environment:
System: FreeBSD nuuk.fillmore-labs.com 4.10-STABLE

>Description:

tcsh uses source -h to read the .history file on logon. This parses the
.history file with normal shell script syntax, interpreting the hash
character as the start of an comment.

This cuts of all commands at `#', which is annoying. Moreover, history
time specifications are parsed in the middle of the line.

This patch lets source -h do some special parsing, so that comments are
only recognized when they start a line. While this is not perfect, it
should be reasonably backwards compatible and fixes all real world cases
I can think of.

Upstream developers (tcsh-bugs at mx.gw.com) notified.

>How-To-Repeat:

add
  set savehist = (100 merge)
to ~/.cshrc

do
  find /usr/src -name .#\*
  echo abc #+1131458139 def
  vi #irclog

log out, log in, do

  history | tail

especially the `echo' is hard to get rid of

>Fix:

The following patch should apply to -CURRENT and -STABLE. It makes enterhist
(= `-h' flag) global and changes parsing in lex accordingly.

Index: tcsh/sh.c
===================================================================
RCS file: /home/ncvs/src/contrib/tcsh/sh.c,v
retrieving revision 1.1.1.2.2.5
diff -u -r1.1.1.2.2.5 sh.c
--- tcsh/sh.c	10 Aug 2002 18:14:44 -0000	1.1.1.2.2.5
+++ tcsh/sh.c	9 May 2004 13:14:32 -0000
@@ -114,7 +114,7 @@
 static bool    batch = 0;
 static bool    mflag = 0;
 static bool    prompt = 1;
-static int     enterhist = 0;
+int     enterhist = 0;
 bool    tellwhat = 0;
 time_t  t_period;
 Char  *ffile = NULL;
Index: tcsh/sh.lex.c
===================================================================
RCS file: /home/ncvs/src/contrib/tcsh/sh.lex.c,v
retrieving revision 1.1.1.2.2.3
diff -u -r1.1.1.2.2.3 sh.lex.c
--- tcsh/sh.lex.c	10 Aug 2002 18:14:45 -0000	1.1.1.2.2.3
+++ tcsh/sh.lex.c	9 May 2004 13:38:29 -0000
@@ -47,7 +47,7 @@
  * There is some involved processing here, because of the complications
  * of input buffering, and especially because of history substitution.
  */
-static	Char		*word		__P((void));
+static	Char		*word		__P((int));
 static	int	 	 getC1		__P((int));
 static	void	 	 getdol		__P((void));
 static	void	 	 getexcl	__P((int));
@@ -137,6 +137,11 @@
 static time_t a2time_t __P((Char *));
 
 /*
+ * special parsing rules apply for source -h
+ */
+extern int enterhist;
+
+/*
  * for history event processing
  * in the command 'echo !?foo?:1 !$' we want the !$ to expand from the line
  * 'foo' was found instead of the last command
@@ -149,6 +154,7 @@
 {
     struct wordent *wdp;
     int     c;
+    int     parsehtime = enterhist;
 
 
     uselastevent = 1;
@@ -183,7 +189,8 @@
 	wdp->next = new;
 	hp->prev = new;
 	wdp = new;
-	wdp->word = word();
+	wdp->word = word(parsehtime);
+	parsehtime = 0;
     } while (wdp->word[0] != '\n');
     if (histlinep < histline + BUFSIZE) {
 	*histlinep = '\0';
@@ -282,7 +289,8 @@
 }
 
 static Char *
-word()
+word(parsehtime)
+    int parsehtime;
 {
     Char c, c1;
     Char *wp;
@@ -315,18 +323,20 @@
 	    goto ret;
 
 	case '#':
-	    if (intty)
+	    if (intty || (enterhist && !parsehtime))
 		break;
 	    c = 0;
 	    h = 0;
 	    do {
 		c1 = c;
 		c = getC(0);
-		if (h < 12)
+		if (h < 11 && parsehtime)
 		    hbuf[h++] = c;
 	    } while (c != '\n');
-	    hbuf[11] = '\0';
-	    Htime = a2time_t(hbuf); 
+	    if (parsehtime) {
+		hbuf[11] = '\0';
+		Htime = a2time_t(hbuf); 
+	    }
 	    if (c1 == '\\')
 		goto loop;
 	    /*FALLTHROUGH*/
@@ -416,7 +426,7 @@
 		c1 = c;
 		dolflg = c == '"' ? DOALL : DOEXCL;
 	    }
-	    else if (c != '#' || !intty) {
+	    else if (c != '#' || (!intty && !enterhist)) {
 		ungetC(c);
 		break;
 	    }

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list