Description: Adjust for differences between BSD and GNU glob
 See detailed code comments.
Bug-Debian: http://bugs.debian.org/88780
Bug-Debian: http://bugs.debian.org/106097
Bug-Debian: http://bugs.debian.org/220170
Bug-Debian: http://bugs.debian.org/350869
Bug-GNU: http://sourceware.org/bugzilla/show_bug.cgi?id=1342
Forwarded: not-needed
Author: Matej Vela <vela@debian.org>
Last-Update: 2011-05-13

Index: csh-20110502/glob.c
===================================================================
--- csh-20110502.orig/glob.c
+++ csh-20110502/glob.c
@@ -370,46 +370,99 @@
 static Char **
 libglob(Char **vl)
 {
-    int     gflgs = GLOB_QUOTE | GLOB_NOMAGIC;
+    Char  **nv, **nvp;
+    size_t  size = GLOBSPACE;
     glob_t  globv;
-    char   *ptr;
     int     nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
 
     if (!vl || !vl[0])
 	return (vl);
 
-    globv.gl_offs = 0;
-    globv.gl_pathv = 0;
-    globv.gl_pathc = 0;
-
-    if (nonomatch)
-	gflgs |= GLOB_NOCHECK;
-
+    nvp = nv = (Char **) xmalloc(sizeof(Char *) * size);
     do {
-	ptr = short2qstr(*vl);
-	switch (glob(ptr, gflgs, 0, &globv)) {
-	case GLOB_ABORTED:
-	    setname(vis_str(*vl));
-	    stderror(ERR_NAME | ERR_GLOB);
-	    /* NOTREACHED */
-	case GLOB_NOSPACE:
-	    stderror(ERR_NOMEM);
-	    /* NOTREACHED */
-	default:
-	    break;
+	int append;			/* Matches to append in this round. */
+	Char *magicp;
+	/*
+	 * The original code depends on GLOB_NOMAGIC and GLOB_MAGCHAR to
+	 * distinguish patterns with magic characters.  Both are unreliable
+	 * with GNU glob() as it considers a pattern magical as soon as it
+	 * finds backslashes (unlike BSD).  tglob() already implements a
+	 * similar check for the whole list, so do it on our own: make
+	 * magicp point to the first magic character, or NUL if none.
+	 */
+	for (magicp = *vl; *magicp; magicp++)
+	    if (isglob(*magicp))
+		break;
+	if (*magicp) {
+	    /*
+	     * Pattern is magic and we need to glob().  The original code
+	     * calls glob() repeatedly on a single output buffer, relying on
+	     * GLOB_NOMAGIC to append the original pattern if it didn't
+	     * contain any magic characters, or GLOB_NOCHECK to do the same
+	     * if nonomatch is in effect.  Again, both are problematic with
+	     * GNU glob() as it leaves backslashes unstripped in the output:
+	     * <http://sourceware.org/bugzilla/show_bug.cgi?id=1342>.  This
+	     * may get fixed at some point, but for now we can't reliably
+	     * append an unchanged pattern to an existing glob buffer, and
+	     * must call glob() separately each time.
+	     */
+	    char *ptr = short2qstr(*vl);
+	    globv.gl_offs = 0;
+	    globv.gl_pathv = 0;
+	    globv.gl_pathc = 0;
+	    switch (glob(ptr, 0, 0, &globv)) {
+	    case GLOB_ABORTED:
+		setname(vis_str(*vl));
+		stderror(ERR_NAME | ERR_GLOB);
+		/* NOTREACHED */
+	    case GLOB_NOSPACE:
+		stderror(ERR_NOMEM);
+		/* NOTREACHED */
+	    default:
+		break;
+	    }
+	    /*
+	     * If gl_pathc shows matches, append that many.  Otherwise
+	     * append the original pattern if nonomatch is in effect.
+	     */
+	    append = globv.gl_pathc ? globv.gl_pathc : nonomatch;
+	    match |= (append != 0);	/* Did any magic patterns match? */
+	    magic = 1;			/* At least one should match. */
+	} else {
+	    /*
+	     * No magic characters, append the pattern by itself.
+	     */
+	    append = 1;
 	}
-	if (globv.gl_flags & GLOB_MAGCHAR) {
-	    match |= (globv.gl_matchc != 0);
-	    magic = 1;
+	if (append) {
+	    if (nvp + append >= nv + size) {
+		size = (nvp - nv) + append + GLOBSPACE;
+		nv = xrealloc((ptr_t) nv, sizeof(Char *) * size);
+		nvp = nv + size - append - GLOBSPACE;
+	    }
+	    if (*magicp && globv.gl_pathc) {
+		char **gvp;
+		for (gvp = globv.gl_pathv; *gvp; gvp++)
+		    *nvp++ = SAVE(*gvp);
+	    } else {
+		*nvp++ = strip(Strsave(*vl));
+	    }
 	}
-	gflgs |= GLOB_APPEND;
+	if (*magicp)
+	    globfree(&globv);		/* Must free regardless of matches. */
     }
     while (*++vl)
 	;
-    vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
-	NULL : blk2short(globv.gl_pathv);
-    globfree(&globv);
-    return (vl);
+    if (nvp == nv || (magic && !match)) {
+	/*
+	 * Output is empty, or none of the magic patterns matched.
+	 * It's up to the caller to generate a "No match" error.
+	 */
+	xfree(nv);
+	return (NULL);
+    }
+    *nvp = NULL;
+    return (nv);
 }
 
 Char   *
