From vcrhonek at redhat.com Wed Jul 1 18:56:40 2009 From: vcrhonek at redhat.com (Vitezslav Crhonek) Date: Wed, 1 Jul 2009 11:56:40 -0400 (EDT) Subject: Tcsh globbing causes bad automount In-Reply-To: <920920190.802731246462110623.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com> Message-ID: <926010301.805131246463800511.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com> Hi, Running a command like "echo FAIL *" while the working directory is the root of a wildcard automount directory will produce lots of invalid automount attempts. /bin/tcsh $ cd /home $ echo FAILURES * You'll see syslog entries like: Jun 30 11:58:24 norcus automount[19211]: failed to mount /home/FAILURES This is causing additional automount traffic that just adds to the overall load on the system. The problem is in libglob() (sh.glob.c). It calls glob() per word in argument. I think that glob() should be called only for words with glob character included. What do you think? Patch follows. It's slightly tested and seems to work fine, but definitely needs to be carefully reviewed. (Maybe there's an easier way...?) Best regards, Vitezslav Crhonek --- sh.glob.c_old 2009-07-01 16:49:25.000000000 +0200 +++ sh.glob.c 2009-07-01 16:58:27.000000000 +0200 @@ -423,6 +423,14 @@ return (str); } +static char **blkend(char **up) +{ + + while (*up) + up++; + return (up); +} + static Char ** libglob(Char **vl) { @@ -430,6 +438,12 @@ glob_t globv; char *ptr; int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0; + char **snowc = NULL; + char **nowc; + char **globres; + char **sres; + char **res; + int size = GLOBSPACE; if (!vl || !vl[0]) return(vl); @@ -438,35 +452,117 @@ globv.gl_pathv = 0; globv.gl_pathc = 0; + sres = res = (Char **) xmalloc((size_t) (size * sizeof(Char *))); + *res = NULL; + if (nonomatch) gflgs |= GLOB_NOCHECK; do { - ptr = short2qstr(*vl); - switch (glob(ptr, gflgs, 0, &globv)) { - case GLOB_ABEND: - globfree(&globv); - setname(ptr); - stderror(ERR_NAME | ERR_GLOB); - /* NOTREACHED */ - case GLOB_NOSPACE: - globfree(&globv); - stderror(ERR_NOMEM); - /* NOTREACHED */ - default: - break; - } - if (globv.gl_flags & GLOB_MAGCHAR) { - match |= (globv.gl_matchc != 0); - magic = 1; + if (!any(ptr, '?') && !any(ptr, '*') && !any(ptr, '[') && !any(ptr, ']')) + { + if (snowc == NULL) + snowc = nowc = (Char **) xmalloc((size_t) ((blklen(vl) + 1) * sizeof(Char *))); + *nowc++ = SAVE(ptr); + *nowc = NULL; + + continue; + + } + switch (glob(ptr, gflgs, 0, &globv)) { + case GLOB_ABEND: + globfree(&globv); + setname(ptr); + stderror(ERR_NAME | ERR_GLOB); + /* NOTREACHED */ + case GLOB_NOSPACE: + globfree(&globv); + stderror(ERR_NOMEM); + /* NOTREACHED */ + default: + break; + } + if (globv.gl_flags & GLOB_MAGCHAR) { + match |= (globv.gl_matchc != 0); + magic = 1; + } + + globres = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? + NULL : blk2short(globv.gl_pathv); + + if (snowc != NULL) + { + while ((blklen(sres) + blklen(snowc)) >= size) { + size += GLOBSPACE; + sres = (Char **) xrealloc((ptr_t) sres, (size_t) (size * sizeof(Char *))); + } + + if (blklen(sres) == 0) + { + sres = blkcpy(sres, snowc); + res = blkend(sres); + } + else + { + res = blkend(sres); + res = blkcpy(res, snowc); + } + xfree(snowc); + snowc = NULL; + } + + if (globres != NULL) + { + while ((blklen(sres) + blklen(globres)) >= size) { + size += GLOBSPACE; + sres = (Char **) xrealloc((ptr_t) sres, (size_t) (size * sizeof(Char *))); + } + + if (blklen(sres) == 0) + { + sres = blkcpy(sres, globres); + res = blkend(sres); + } + else + { + res = blkend(sres); + res = blkcpy(res, globres); + } + xfree(globres); + globres = NULL; } - gflgs |= GLOB_APPEND; + + globfree(&globv); } while (*++vl); - vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? - NULL : blk2short(globv.gl_pathv); - globfree(&globv); - return (vl); + + if (snowc != NULL) + { + while ((blklen(sres) + blklen(snowc)) >= size) { + size += GLOBSPACE; + sres = (Char **) xrealloc((ptr_t) sres, (size_t) (size * sizeof(Char *))); + } + + if (blklen(sres) == 0) + { + sres = blkcpy(sres, snowc); + res = blkend(sres); + } + else + { + res = blkend(sres); + res = blkcpy(res, snowc); + } + xfree(snowc); + snowc = NULL; + } + + if (blklen(sres) != 0) + vl = saveblk(sres); + else + vl = NULL; + + return vl; } Char * From christos at zoulas.com Wed Jul 1 22:58:33 2009 From: christos at zoulas.com (Christos Zoulas) Date: Wed, 1 Jul 2009 15:58:33 -0400 Subject: Tcsh globbing causes bad automount In-Reply-To: <926010301.805131246463800511.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com> from Vitezslav Crhonek (Jul 1, 11:56am) Message-ID: <20090701195833.53D335654E@rebar.astron.com> On Jul 1, 11:56am, vcrhonek at redhat.com (Vitezslav Crhonek) wrote: -- Subject: Tcsh globbing causes bad automount | Hi, | | Running a command like "echo FAIL *" while the working | directory is the root of a wildcard automount directory will | produce lots of invalid automount attempts. | | /bin/tcsh | $ cd /home | $ echo FAILURES * | | You'll see syslog entries like: | Jun 30 11:58:24 norcus automount[19211]: failed to mount | /home/FAILURES | | This is causing additional automount traffic that just adds | to the overall load on the system. | | The problem is in libglob() (sh.glob.c). It calls glob() per word | in argument. I think that glob() should be called only for | words with glob character included. What do you think? | | Patch follows. It's slightly tested and seems to work fine, but | definitely needs to be carefully reviewed. (Maybe there's an easier | way...?) | | Best regards, | Vitezslav Crhonek Sounds reasonable, but I would prefer to split tglob() into two functions, one that remains as is and a tglob1() that tests only a simple string. Then tglob can use tglob1(). The second step would be to add a glob1() similarly, that appends to a result of globbed results and uses tglob1 to determine what to do. Then you can write globall in terms of that tglob1. This would make the code more efficient. christos From christos at zoulas.com Fri Jul 10 20:32:29 2009 From: christos at zoulas.com (Christos Zoulas) Date: Fri, 10 Jul 2009 13:32:29 -0400 Subject: tcsh-6.17.00 is now available Message-ID: <20090710173230.08AA45654E@rebar.astron.com> Hello, I am pleased to announce that tcsh-6.17 is now available; this is a mainly a bug fix release with the exception of these three feature additions: 10. always save the whole command, not just the first 80 chars of it. 4. Add autoexpand=onlyhistory (Don Estabrook, m66) 3. Add history in loops (Laurence Darby, m48) Please consult the Fixes files for a complete list of changes. Tcsh is an enhanced version of the Berkeley C-shell that offers command line editing and completion plus many other little things that preserve the length of your fingers. Tcsh runs on most UNIX machines, VMS_POSIX, OS/2 EMX, WIN32, Amiga... You can get tcsh from ftp://ftp.astron.com/pub/tcsh/tcsh-6.17.00.tar.gz or from the mirrors: ftp://ftp.gw.com/pub/unix/tcsh/tcsh-6.17.00.tar.gz [US] ftp://ftp.funet.fi/pub/unix/shells/tcsh/tcsh-6.17.00.tar.gz [Finland] RMD160 (tcsh-6.17.00.tar.gz) = 2cc41a895799ade6d62640f877bb626f136dac35 This is a gzip (GNU zip) tar archive. If you don't have GNU zip you can get it from ftp.gnu.org or other GNU mirrors. I would like to thank: * everyone who sent bug reports * the beta team for all their help, bug fixes, and suggestions christos