129301572SMark Peek /* $Header: /src/pub/tcsh/sh.exp.c,v 3.40 2002/03/08 17:36:46 christos Exp $ */ 2c80476e4SDavid E. O'Brien /* 3c80476e4SDavid E. O'Brien * sh.exp.c: Expression evaluations 4c80476e4SDavid E. O'Brien */ 5c80476e4SDavid E. O'Brien /*- 6c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California. 7c80476e4SDavid E. O'Brien * All rights reserved. 8c80476e4SDavid E. O'Brien * 9c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 10c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions 11c80476e4SDavid E. O'Brien * are met: 12c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 13c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 14c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 15c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 16c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 1729301572SMark Peek * 3. Neither the name of the University nor the names of its contributors 18c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 19c80476e4SDavid E. O'Brien * without specific prior written permission. 20c80476e4SDavid E. O'Brien * 21c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c80476e4SDavid E. O'Brien * SUCH DAMAGE. 32c80476e4SDavid E. O'Brien */ 33c80476e4SDavid E. O'Brien #include "sh.h" 34c80476e4SDavid E. O'Brien 3529301572SMark Peek RCSID("$Id: sh.exp.c,v 3.40 2002/03/08 17:36:46 christos Exp $") 3629301572SMark Peek 3729301572SMark Peek #include "tw.h" 38c80476e4SDavid E. O'Brien 39c80476e4SDavid E. O'Brien /* 40c80476e4SDavid E. O'Brien * C shell 41c80476e4SDavid E. O'Brien */ 42c80476e4SDavid E. O'Brien 43c80476e4SDavid E. O'Brien #define TEXP_IGNORE 1 /* in ignore, it means to ignore value, just parse */ 44c80476e4SDavid E. O'Brien #define TEXP_NOGLOB 2 /* in ignore, it means not to globone */ 45c80476e4SDavid E. O'Brien 46c80476e4SDavid E. O'Brien #define ADDOP 1 47c80476e4SDavid E. O'Brien #define MULOP 2 48c80476e4SDavid E. O'Brien #define EQOP 4 49c80476e4SDavid E. O'Brien #define RELOP 8 50c80476e4SDavid E. O'Brien #define RESTOP 16 51c80476e4SDavid E. O'Brien #define ANYOP 31 52c80476e4SDavid E. O'Brien 53c80476e4SDavid E. O'Brien #define EQEQ 1 54c80476e4SDavid E. O'Brien #define GTR 2 55c80476e4SDavid E. O'Brien #define LSS 4 56c80476e4SDavid E. O'Brien #define NOTEQ 6 57c80476e4SDavid E. O'Brien #define EQMATCH 7 58c80476e4SDavid E. O'Brien #define NOTEQMATCH 8 59c80476e4SDavid E. O'Brien 60c80476e4SDavid E. O'Brien static int sh_access __P((Char *, int)); 61c80476e4SDavid E. O'Brien static int exp1 __P((Char ***, bool)); 62c80476e4SDavid E. O'Brien static int exp2 __P((Char ***, bool)); 63c80476e4SDavid E. O'Brien static int exp2a __P((Char ***, bool)); 64c80476e4SDavid E. O'Brien static int exp2b __P((Char ***, bool)); 65c80476e4SDavid E. O'Brien static int exp2c __P((Char ***, bool)); 66c80476e4SDavid E. O'Brien static Char *exp3 __P((Char ***, bool)); 67c80476e4SDavid E. O'Brien static Char *exp3a __P((Char ***, bool)); 68c80476e4SDavid E. O'Brien static Char *exp4 __P((Char ***, bool)); 69c80476e4SDavid E. O'Brien static Char *exp5 __P((Char ***, bool)); 70c80476e4SDavid E. O'Brien static Char *exp6 __P((Char ***, bool)); 71c80476e4SDavid E. O'Brien static void evalav __P((Char **)); 72c80476e4SDavid E. O'Brien static int isa __P((Char *, int)); 73c80476e4SDavid E. O'Brien static int egetn __P((Char *)); 74c80476e4SDavid E. O'Brien 75c80476e4SDavid E. O'Brien 76c80476e4SDavid E. O'Brien #ifdef EDEBUG 77c80476e4SDavid E. O'Brien static void etracc __P((char *, Char *, Char ***)); 78c80476e4SDavid E. O'Brien static void etraci __P((char *, int, Char ***)); 79c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 80c80476e4SDavid E. O'Brien 81c80476e4SDavid E. O'Brien 82c80476e4SDavid E. O'Brien /* 83c80476e4SDavid E. O'Brien * shell access function according to POSIX and non POSIX 84c80476e4SDavid E. O'Brien * From Beto Appleton (beto@aixwiz.aix.ibm.com) 85c80476e4SDavid E. O'Brien */ 86c80476e4SDavid E. O'Brien static int 87c80476e4SDavid E. O'Brien sh_access(fname, mode) 88c80476e4SDavid E. O'Brien Char *fname; 89c80476e4SDavid E. O'Brien int mode; 90c80476e4SDavid E. O'Brien { 91c80476e4SDavid E. O'Brien #if defined(POSIX) && !defined(USE_ACCESS) 92c80476e4SDavid E. O'Brien struct stat statb; 93c80476e4SDavid E. O'Brien #endif /* POSIX */ 94c80476e4SDavid E. O'Brien char *name = short2str(fname); 95c80476e4SDavid E. O'Brien 96c80476e4SDavid E. O'Brien if (*name == '\0') 97c80476e4SDavid E. O'Brien return 1; 98c80476e4SDavid E. O'Brien 99c80476e4SDavid E. O'Brien #if !defined(POSIX) || defined(USE_ACCESS) 100c80476e4SDavid E. O'Brien return access(name, mode); 101c80476e4SDavid E. O'Brien #else /* POSIX */ 102c80476e4SDavid E. O'Brien 103c80476e4SDavid E. O'Brien /* 104c80476e4SDavid E. O'Brien * POSIX 1003.2-d11.2 105c80476e4SDavid E. O'Brien * -r file True if file exists and is readable. 106c80476e4SDavid E. O'Brien * -w file True if file exists and is writable. 107c80476e4SDavid E. O'Brien * True shall indicate only that the write flag is on. 108c80476e4SDavid E. O'Brien * The file shall not be writable on a read-only file 109c80476e4SDavid E. O'Brien * system even if this test indicates true. 110c80476e4SDavid E. O'Brien * -x file True if file exists and is executable. 111c80476e4SDavid E. O'Brien * True shall indicate only that the execute flag is on. 112c80476e4SDavid E. O'Brien * If file is a directory, true indicates that the file 113c80476e4SDavid E. O'Brien * can be searched. 114c80476e4SDavid E. O'Brien */ 115c80476e4SDavid E. O'Brien if (mode != W_OK && mode != X_OK) 116c80476e4SDavid E. O'Brien return access(name, mode); 117c80476e4SDavid E. O'Brien 118c80476e4SDavid E. O'Brien if (stat(name, &statb) == -1) 119c80476e4SDavid E. O'Brien return 1; 120c80476e4SDavid E. O'Brien 121c80476e4SDavid E. O'Brien if (access(name, mode) == 0) { 122c80476e4SDavid E. O'Brien #ifdef S_ISDIR 123c80476e4SDavid E. O'Brien if (S_ISDIR(statb.st_mode) && mode == X_OK) 124c80476e4SDavid E. O'Brien return 0; 125c80476e4SDavid E. O'Brien #endif /* S_ISDIR */ 126c80476e4SDavid E. O'Brien 127c80476e4SDavid E. O'Brien /* root needs permission for someone */ 128c80476e4SDavid E. O'Brien switch (mode) { 129c80476e4SDavid E. O'Brien case W_OK: 130c80476e4SDavid E. O'Brien mode = S_IWUSR | S_IWGRP | S_IWOTH; 131c80476e4SDavid E. O'Brien break; 132c80476e4SDavid E. O'Brien case X_OK: 133c80476e4SDavid E. O'Brien mode = S_IXUSR | S_IXGRP | S_IXOTH; 134c80476e4SDavid E. O'Brien break; 135c80476e4SDavid E. O'Brien default: 136c80476e4SDavid E. O'Brien abort(); 137c80476e4SDavid E. O'Brien break; 138c80476e4SDavid E. O'Brien } 139c80476e4SDavid E. O'Brien 140c80476e4SDavid E. O'Brien } 141c80476e4SDavid E. O'Brien 142c80476e4SDavid E. O'Brien else if (euid == statb.st_uid) 143c80476e4SDavid E. O'Brien mode <<= 6; 144c80476e4SDavid E. O'Brien 145c80476e4SDavid E. O'Brien else if (egid == statb.st_gid) 146c80476e4SDavid E. O'Brien mode <<= 3; 147c80476e4SDavid E. O'Brien 148c80476e4SDavid E. O'Brien # ifdef NGROUPS_MAX 149c80476e4SDavid E. O'Brien else { 150c80476e4SDavid E. O'Brien # if defined(__386BSD__) || defined(BSD4_4) 151c80476e4SDavid E. O'Brien /* 152c80476e4SDavid E. O'Brien * These two decided that setgroup() should take an array of int's 153c80476e4SDavid E. O'Brien * and they define _SC_NGROUPS_MAX without having sysconf 154c80476e4SDavid E. O'Brien */ 155c80476e4SDavid E. O'Brien # undef _SC_NGROUPS_MAX 156c80476e4SDavid E. O'Brien # if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) 157c80476e4SDavid E. O'Brien # define GID_T gid_t 158c80476e4SDavid E. O'Brien # else 159c80476e4SDavid E. O'Brien # define GID_T int 160c80476e4SDavid E. O'Brien # endif 161c80476e4SDavid E. O'Brien # else 162c80476e4SDavid E. O'Brien # define GID_T gid_t 163c80476e4SDavid E. O'Brien # endif /* __386BSD__ || BSD4_4 */ 164c80476e4SDavid E. O'Brien /* you can be in several groups */ 165c80476e4SDavid E. O'Brien long n; 166c80476e4SDavid E. O'Brien GID_T *groups; 167c80476e4SDavid E. O'Brien 168c80476e4SDavid E. O'Brien /* 169c80476e4SDavid E. O'Brien * Try these things to find a positive maximum groups value: 170c80476e4SDavid E. O'Brien * 1) sysconf(_SC_NGROUPS_MAX) 171c80476e4SDavid E. O'Brien * 2) NGROUPS_MAX 172c80476e4SDavid E. O'Brien * 3) getgroups(0, unused) 173c80476e4SDavid E. O'Brien * Then allocate and scan the groups array if one of these worked. 174c80476e4SDavid E. O'Brien */ 175c80476e4SDavid E. O'Brien # ifdef _SC_NGROUPS_MAX 176c80476e4SDavid E. O'Brien if ((n = sysconf(_SC_NGROUPS_MAX)) == -1) 177c80476e4SDavid E. O'Brien # endif /* _SC_NGROUPS_MAX */ 178c80476e4SDavid E. O'Brien n = NGROUPS_MAX; 179c80476e4SDavid E. O'Brien if (n <= 0) 180c80476e4SDavid E. O'Brien n = getgroups(0, (GID_T *) NULL); 181c80476e4SDavid E. O'Brien 182c80476e4SDavid E. O'Brien if (n > 0) { 183c80476e4SDavid E. O'Brien groups = (GID_T *) xmalloc((size_t) (n * sizeof(GID_T))); 184c80476e4SDavid E. O'Brien n = getgroups((int) n, groups); 185c80476e4SDavid E. O'Brien while (--n >= 0) 186c80476e4SDavid E. O'Brien if (groups[n] == statb.st_gid) { 187c80476e4SDavid E. O'Brien mode <<= 3; 188c80476e4SDavid E. O'Brien break; 189c80476e4SDavid E. O'Brien } 190c80476e4SDavid E. O'Brien } 191c80476e4SDavid E. O'Brien } 192c80476e4SDavid E. O'Brien # endif /* NGROUPS_MAX */ 193c80476e4SDavid E. O'Brien 194c80476e4SDavid E. O'Brien if (statb.st_mode & mode) 195c80476e4SDavid E. O'Brien return 0; 196c80476e4SDavid E. O'Brien else 197c80476e4SDavid E. O'Brien return 1; 198c80476e4SDavid E. O'Brien #endif /* !POSIX */ 199c80476e4SDavid E. O'Brien } 200c80476e4SDavid E. O'Brien 201c80476e4SDavid E. O'Brien int 202c80476e4SDavid E. O'Brien expr(vp) 203c80476e4SDavid E. O'Brien register Char ***vp; 204c80476e4SDavid E. O'Brien { 205c80476e4SDavid E. O'Brien return (exp0(vp, 0)); 206c80476e4SDavid E. O'Brien } 207c80476e4SDavid E. O'Brien 208c80476e4SDavid E. O'Brien int 209c80476e4SDavid E. O'Brien exp0(vp, ignore) 210c80476e4SDavid E. O'Brien register Char ***vp; 211c80476e4SDavid E. O'Brien bool ignore; 212c80476e4SDavid E. O'Brien { 213c80476e4SDavid E. O'Brien register int p1 = exp1(vp, ignore); 214c80476e4SDavid E. O'Brien 215c80476e4SDavid E. O'Brien #ifdef EDEBUG 216c80476e4SDavid E. O'Brien etraci("exp0 p1", p1, vp); 217c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 218c80476e4SDavid E. O'Brien if (**vp && eq(**vp, STRor2)) { 219c80476e4SDavid E. O'Brien register int p2; 220c80476e4SDavid E. O'Brien 221c80476e4SDavid E. O'Brien (*vp)++; 222c80476e4SDavid E. O'Brien p2 = exp0(vp, (ignore & TEXP_IGNORE) || p1); 223c80476e4SDavid E. O'Brien #ifdef EDEBUG 224c80476e4SDavid E. O'Brien etraci("exp0 p2", p2, vp); 225c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 226c80476e4SDavid E. O'Brien return (p1 || p2); 227c80476e4SDavid E. O'Brien } 228c80476e4SDavid E. O'Brien return (p1); 229c80476e4SDavid E. O'Brien } 230c80476e4SDavid E. O'Brien 231c80476e4SDavid E. O'Brien static int 232c80476e4SDavid E. O'Brien exp1(vp, ignore) 233c80476e4SDavid E. O'Brien register Char ***vp; 234c80476e4SDavid E. O'Brien bool ignore; 235c80476e4SDavid E. O'Brien { 236c80476e4SDavid E. O'Brien register int p1 = exp2(vp, ignore); 237c80476e4SDavid E. O'Brien 238c80476e4SDavid E. O'Brien #ifdef EDEBUG 239c80476e4SDavid E. O'Brien etraci("exp1 p1", p1, vp); 240c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 241c80476e4SDavid E. O'Brien if (**vp && eq(**vp, STRand2)) { 242c80476e4SDavid E. O'Brien register int p2; 243c80476e4SDavid E. O'Brien 244c80476e4SDavid E. O'Brien (*vp)++; 245c80476e4SDavid E. O'Brien p2 = exp1(vp, (ignore & TEXP_IGNORE) || !p1); 246c80476e4SDavid E. O'Brien #ifdef EDEBUG 247c80476e4SDavid E. O'Brien etraci("exp1 p2", p2, vp); 248c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 249c80476e4SDavid E. O'Brien return (p1 && p2); 250c80476e4SDavid E. O'Brien } 251c80476e4SDavid E. O'Brien return (p1); 252c80476e4SDavid E. O'Brien } 253c80476e4SDavid E. O'Brien 254c80476e4SDavid E. O'Brien static int 255c80476e4SDavid E. O'Brien exp2(vp, ignore) 256c80476e4SDavid E. O'Brien register Char ***vp; 257c80476e4SDavid E. O'Brien bool ignore; 258c80476e4SDavid E. O'Brien { 259c80476e4SDavid E. O'Brien register int p1 = exp2a(vp, ignore); 260c80476e4SDavid E. O'Brien 261c80476e4SDavid E. O'Brien #ifdef EDEBUG 262c80476e4SDavid E. O'Brien etraci("exp3 p1", p1, vp); 263c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 264c80476e4SDavid E. O'Brien if (**vp && eq(**vp, STRor)) { 265c80476e4SDavid E. O'Brien register int p2; 266c80476e4SDavid E. O'Brien 267c80476e4SDavid E. O'Brien (*vp)++; 268c80476e4SDavid E. O'Brien p2 = exp2(vp, ignore); 269c80476e4SDavid E. O'Brien #ifdef EDEBUG 270c80476e4SDavid E. O'Brien etraci("exp3 p2", p2, vp); 271c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 272c80476e4SDavid E. O'Brien return (p1 | p2); 273c80476e4SDavid E. O'Brien } 274c80476e4SDavid E. O'Brien return (p1); 275c80476e4SDavid E. O'Brien } 276c80476e4SDavid E. O'Brien 277c80476e4SDavid E. O'Brien static int 278c80476e4SDavid E. O'Brien exp2a(vp, ignore) 279c80476e4SDavid E. O'Brien register Char ***vp; 280c80476e4SDavid E. O'Brien bool ignore; 281c80476e4SDavid E. O'Brien { 282c80476e4SDavid E. O'Brien register int p1 = exp2b(vp, ignore); 283c80476e4SDavid E. O'Brien 284c80476e4SDavid E. O'Brien #ifdef EDEBUG 285c80476e4SDavid E. O'Brien etraci("exp2a p1", p1, vp); 286c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 287c80476e4SDavid E. O'Brien if (**vp && eq(**vp, STRcaret)) { 288c80476e4SDavid E. O'Brien register int p2; 289c80476e4SDavid E. O'Brien 290c80476e4SDavid E. O'Brien (*vp)++; 291c80476e4SDavid E. O'Brien p2 = exp2a(vp, ignore); 292c80476e4SDavid E. O'Brien #ifdef EDEBUG 293c80476e4SDavid E. O'Brien etraci("exp2a p2", p2, vp); 294c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 295c80476e4SDavid E. O'Brien return (p1 ^ p2); 296c80476e4SDavid E. O'Brien } 297c80476e4SDavid E. O'Brien return (p1); 298c80476e4SDavid E. O'Brien } 299c80476e4SDavid E. O'Brien 300c80476e4SDavid E. O'Brien static int 301c80476e4SDavid E. O'Brien exp2b(vp, ignore) 302c80476e4SDavid E. O'Brien register Char ***vp; 303c80476e4SDavid E. O'Brien bool ignore; 304c80476e4SDavid E. O'Brien { 305c80476e4SDavid E. O'Brien register int p1 = exp2c(vp, ignore); 306c80476e4SDavid E. O'Brien 307c80476e4SDavid E. O'Brien #ifdef EDEBUG 308c80476e4SDavid E. O'Brien etraci("exp2b p1", p1, vp); 309c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 310c80476e4SDavid E. O'Brien if (**vp && eq(**vp, STRand)) { 311c80476e4SDavid E. O'Brien register int p2; 312c80476e4SDavid E. O'Brien 313c80476e4SDavid E. O'Brien (*vp)++; 314c80476e4SDavid E. O'Brien p2 = exp2b(vp, ignore); 315c80476e4SDavid E. O'Brien #ifdef EDEBUG 316c80476e4SDavid E. O'Brien etraci("exp2b p2", p2, vp); 317c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 318c80476e4SDavid E. O'Brien return (p1 & p2); 319c80476e4SDavid E. O'Brien } 320c80476e4SDavid E. O'Brien return (p1); 321c80476e4SDavid E. O'Brien } 322c80476e4SDavid E. O'Brien 323c80476e4SDavid E. O'Brien static int 324c80476e4SDavid E. O'Brien exp2c(vp, ignore) 325c80476e4SDavid E. O'Brien register Char ***vp; 326c80476e4SDavid E. O'Brien bool ignore; 327c80476e4SDavid E. O'Brien { 328c80476e4SDavid E. O'Brien register Char *p1 = exp3(vp, ignore); 329c80476e4SDavid E. O'Brien register Char *p2; 330c80476e4SDavid E. O'Brien register int i; 331c80476e4SDavid E. O'Brien 332c80476e4SDavid E. O'Brien #ifdef EDEBUG 333c80476e4SDavid E. O'Brien etracc("exp2c p1", p1, vp); 334c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 335c80476e4SDavid E. O'Brien if ((i = isa(**vp, EQOP)) != 0) { 336c80476e4SDavid E. O'Brien (*vp)++; 337c80476e4SDavid E. O'Brien if (i == EQMATCH || i == NOTEQMATCH) 338c80476e4SDavid E. O'Brien ignore |= TEXP_NOGLOB; 339c80476e4SDavid E. O'Brien p2 = exp3(vp, ignore); 340c80476e4SDavid E. O'Brien #ifdef EDEBUG 341c80476e4SDavid E. O'Brien etracc("exp2c p2", p2, vp); 342c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 343c80476e4SDavid E. O'Brien if (!(ignore & TEXP_IGNORE)) 344c80476e4SDavid E. O'Brien switch (i) { 345c80476e4SDavid E. O'Brien 346c80476e4SDavid E. O'Brien case EQEQ: 347c80476e4SDavid E. O'Brien i = eq(p1, p2); 348c80476e4SDavid E. O'Brien break; 349c80476e4SDavid E. O'Brien 350c80476e4SDavid E. O'Brien case NOTEQ: 351c80476e4SDavid E. O'Brien i = !eq(p1, p2); 352c80476e4SDavid E. O'Brien break; 353c80476e4SDavid E. O'Brien 354c80476e4SDavid E. O'Brien case EQMATCH: 355c80476e4SDavid E. O'Brien i = Gmatch(p1, p2); 356c80476e4SDavid E. O'Brien break; 357c80476e4SDavid E. O'Brien 358c80476e4SDavid E. O'Brien case NOTEQMATCH: 359c80476e4SDavid E. O'Brien i = !Gmatch(p1, p2); 360c80476e4SDavid E. O'Brien break; 361c80476e4SDavid E. O'Brien } 362c80476e4SDavid E. O'Brien xfree((ptr_t) p1); 363c80476e4SDavid E. O'Brien xfree((ptr_t) p2); 364c80476e4SDavid E. O'Brien return (i); 365c80476e4SDavid E. O'Brien } 366c80476e4SDavid E. O'Brien i = egetn(p1); 367c80476e4SDavid E. O'Brien xfree((ptr_t) p1); 368c80476e4SDavid E. O'Brien return (i); 369c80476e4SDavid E. O'Brien } 370c80476e4SDavid E. O'Brien 371c80476e4SDavid E. O'Brien static Char * 372c80476e4SDavid E. O'Brien exp3(vp, ignore) 373c80476e4SDavid E. O'Brien register Char ***vp; 374c80476e4SDavid E. O'Brien bool ignore; 375c80476e4SDavid E. O'Brien { 376c80476e4SDavid E. O'Brien register Char *p1, *p2; 377c80476e4SDavid E. O'Brien register int i; 378c80476e4SDavid E. O'Brien 379c80476e4SDavid E. O'Brien p1 = exp3a(vp, ignore); 380c80476e4SDavid E. O'Brien #ifdef EDEBUG 381c80476e4SDavid E. O'Brien etracc("exp3 p1", p1, vp); 382c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 383c80476e4SDavid E. O'Brien if ((i = isa(**vp, RELOP)) != 0) { 384c80476e4SDavid E. O'Brien (*vp)++; 385c80476e4SDavid E. O'Brien if (**vp && eq(**vp, STRequal)) 386c80476e4SDavid E. O'Brien i |= 1, (*vp)++; 387c80476e4SDavid E. O'Brien p2 = exp3(vp, ignore); 388c80476e4SDavid E. O'Brien #ifdef EDEBUG 389c80476e4SDavid E. O'Brien etracc("exp3 p2", p2, vp); 390c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 391c80476e4SDavid E. O'Brien if (!(ignore & TEXP_IGNORE)) 392c80476e4SDavid E. O'Brien switch (i) { 393c80476e4SDavid E. O'Brien 394c80476e4SDavid E. O'Brien case GTR: 395c80476e4SDavid E. O'Brien i = egetn(p1) > egetn(p2); 396c80476e4SDavid E. O'Brien break; 397c80476e4SDavid E. O'Brien 398c80476e4SDavid E. O'Brien case GTR | 1: 399c80476e4SDavid E. O'Brien i = egetn(p1) >= egetn(p2); 400c80476e4SDavid E. O'Brien break; 401c80476e4SDavid E. O'Brien 402c80476e4SDavid E. O'Brien case LSS: 403c80476e4SDavid E. O'Brien i = egetn(p1) < egetn(p2); 404c80476e4SDavid E. O'Brien break; 405c80476e4SDavid E. O'Brien 406c80476e4SDavid E. O'Brien case LSS | 1: 407c80476e4SDavid E. O'Brien i = egetn(p1) <= egetn(p2); 408c80476e4SDavid E. O'Brien break; 409c80476e4SDavid E. O'Brien } 410c80476e4SDavid E. O'Brien xfree((ptr_t) p1); 411c80476e4SDavid E. O'Brien xfree((ptr_t) p2); 412c80476e4SDavid E. O'Brien return (putn(i)); 413c80476e4SDavid E. O'Brien } 414c80476e4SDavid E. O'Brien return (p1); 415c80476e4SDavid E. O'Brien } 416c80476e4SDavid E. O'Brien 417c80476e4SDavid E. O'Brien static Char * 418c80476e4SDavid E. O'Brien exp3a(vp, ignore) 419c80476e4SDavid E. O'Brien register Char ***vp; 420c80476e4SDavid E. O'Brien bool ignore; 421c80476e4SDavid E. O'Brien { 422c80476e4SDavid E. O'Brien register Char *p1, *p2, *op; 423c80476e4SDavid E. O'Brien register int i; 424c80476e4SDavid E. O'Brien 425c80476e4SDavid E. O'Brien p1 = exp4(vp, ignore); 426c80476e4SDavid E. O'Brien #ifdef EDEBUG 427c80476e4SDavid E. O'Brien etracc("exp3a p1", p1, vp); 428c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 429c80476e4SDavid E. O'Brien op = **vp; 430c80476e4SDavid E. O'Brien if (op && any("<>", op[0]) && op[0] == op[1]) { 431c80476e4SDavid E. O'Brien (*vp)++; 432c80476e4SDavid E. O'Brien p2 = exp3a(vp, ignore); 433c80476e4SDavid E. O'Brien #ifdef EDEBUG 434c80476e4SDavid E. O'Brien etracc("exp3a p2", p2, vp); 435c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 436c80476e4SDavid E. O'Brien if (op[0] == '<') 437c80476e4SDavid E. O'Brien i = egetn(p1) << egetn(p2); 438c80476e4SDavid E. O'Brien else 439c80476e4SDavid E. O'Brien i = egetn(p1) >> egetn(p2); 440c80476e4SDavid E. O'Brien xfree((ptr_t) p1); 441c80476e4SDavid E. O'Brien xfree((ptr_t) p2); 442c80476e4SDavid E. O'Brien return (putn(i)); 443c80476e4SDavid E. O'Brien } 444c80476e4SDavid E. O'Brien return (p1); 445c80476e4SDavid E. O'Brien } 446c80476e4SDavid E. O'Brien 447c80476e4SDavid E. O'Brien static Char * 448c80476e4SDavid E. O'Brien exp4(vp, ignore) 449c80476e4SDavid E. O'Brien register Char ***vp; 450c80476e4SDavid E. O'Brien bool ignore; 451c80476e4SDavid E. O'Brien { 452c80476e4SDavid E. O'Brien register Char *p1, *p2; 453c80476e4SDavid E. O'Brien register int i = 0; 454c80476e4SDavid E. O'Brien 455c80476e4SDavid E. O'Brien p1 = exp5(vp, ignore); 456c80476e4SDavid E. O'Brien #ifdef EDEBUG 457c80476e4SDavid E. O'Brien etracc("exp4 p1", p1, vp); 458c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 459c80476e4SDavid E. O'Brien if (isa(**vp, ADDOP)) { 460c80476e4SDavid E. O'Brien register Char *op = *(*vp)++; 461c80476e4SDavid E. O'Brien 462c80476e4SDavid E. O'Brien p2 = exp4(vp, ignore); 463c80476e4SDavid E. O'Brien #ifdef EDEBUG 464c80476e4SDavid E. O'Brien etracc("exp4 p2", p2, vp); 465c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 466c80476e4SDavid E. O'Brien if (!(ignore & TEXP_IGNORE)) 467c80476e4SDavid E. O'Brien switch (op[0]) { 468c80476e4SDavid E. O'Brien 469c80476e4SDavid E. O'Brien case '+': 470c80476e4SDavid E. O'Brien i = egetn(p1) + egetn(p2); 471c80476e4SDavid E. O'Brien break; 472c80476e4SDavid E. O'Brien 473c80476e4SDavid E. O'Brien case '-': 474c80476e4SDavid E. O'Brien i = egetn(p1) - egetn(p2); 475c80476e4SDavid E. O'Brien break; 476c80476e4SDavid E. O'Brien } 477c80476e4SDavid E. O'Brien xfree((ptr_t) p1); 478c80476e4SDavid E. O'Brien xfree((ptr_t) p2); 479c80476e4SDavid E. O'Brien return (putn(i)); 480c80476e4SDavid E. O'Brien } 481c80476e4SDavid E. O'Brien return (p1); 482c80476e4SDavid E. O'Brien } 483c80476e4SDavid E. O'Brien 484c80476e4SDavid E. O'Brien static Char * 485c80476e4SDavid E. O'Brien exp5(vp, ignore) 486c80476e4SDavid E. O'Brien register Char ***vp; 487c80476e4SDavid E. O'Brien bool ignore; 488c80476e4SDavid E. O'Brien { 489c80476e4SDavid E. O'Brien register Char *p1, *p2; 490c80476e4SDavid E. O'Brien register int i = 0; 491c80476e4SDavid E. O'Brien 492c80476e4SDavid E. O'Brien p1 = exp6(vp, ignore); 493c80476e4SDavid E. O'Brien #ifdef EDEBUG 494c80476e4SDavid E. O'Brien etracc("exp5 p1", p1, vp); 495c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 496c80476e4SDavid E. O'Brien 497c80476e4SDavid E. O'Brien if (isa(**vp, MULOP)) { 498c80476e4SDavid E. O'Brien register Char *op = *(*vp)++; 499c80476e4SDavid E. O'Brien if ((ignore & TEXP_NOGLOB) != 0) 500c80476e4SDavid E. O'Brien /* 501c80476e4SDavid E. O'Brien * We are just trying to get the right side of 502c80476e4SDavid E. O'Brien * a =~ or !~ operator 503c80476e4SDavid E. O'Brien */ 504c80476e4SDavid E. O'Brien return Strsave(op); 505c80476e4SDavid E. O'Brien 506c80476e4SDavid E. O'Brien p2 = exp5(vp, ignore); 507c80476e4SDavid E. O'Brien #ifdef EDEBUG 508c80476e4SDavid E. O'Brien etracc("exp5 p2", p2, vp); 509c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 510c80476e4SDavid E. O'Brien if (!(ignore & TEXP_IGNORE)) 511c80476e4SDavid E. O'Brien switch (op[0]) { 512c80476e4SDavid E. O'Brien 513c80476e4SDavid E. O'Brien case '*': 514c80476e4SDavid E. O'Brien i = egetn(p1) * egetn(p2); 515c80476e4SDavid E. O'Brien break; 516c80476e4SDavid E. O'Brien 517c80476e4SDavid E. O'Brien case '/': 518c80476e4SDavid E. O'Brien i = egetn(p2); 519c80476e4SDavid E. O'Brien if (i == 0) 520c80476e4SDavid E. O'Brien stderror(ERR_DIV0); 521c80476e4SDavid E. O'Brien i = egetn(p1) / i; 522c80476e4SDavid E. O'Brien break; 523c80476e4SDavid E. O'Brien 524c80476e4SDavid E. O'Brien case '%': 525c80476e4SDavid E. O'Brien i = egetn(p2); 526c80476e4SDavid E. O'Brien if (i == 0) 527c80476e4SDavid E. O'Brien stderror(ERR_MOD0); 528c80476e4SDavid E. O'Brien i = egetn(p1) % i; 529c80476e4SDavid E. O'Brien break; 530c80476e4SDavid E. O'Brien } 531c80476e4SDavid E. O'Brien xfree((ptr_t) p1); 532c80476e4SDavid E. O'Brien xfree((ptr_t) p2); 533c80476e4SDavid E. O'Brien return (putn(i)); 534c80476e4SDavid E. O'Brien } 535c80476e4SDavid E. O'Brien return (p1); 536c80476e4SDavid E. O'Brien } 537c80476e4SDavid E. O'Brien 538c80476e4SDavid E. O'Brien static Char * 539c80476e4SDavid E. O'Brien exp6(vp, ignore) 540c80476e4SDavid E. O'Brien register Char ***vp; 541c80476e4SDavid E. O'Brien bool ignore; 542c80476e4SDavid E. O'Brien { 543c80476e4SDavid E. O'Brien int ccode, i = 0; 544c80476e4SDavid E. O'Brien register Char *cp; 545c80476e4SDavid E. O'Brien 546c80476e4SDavid E. O'Brien if (**vp == 0) 547c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_EXPRESSION); 548c80476e4SDavid E. O'Brien if (eq(**vp, STRbang)) { 549c80476e4SDavid E. O'Brien (*vp)++; 550c80476e4SDavid E. O'Brien cp = exp6(vp, ignore); 551c80476e4SDavid E. O'Brien #ifdef EDEBUG 552c80476e4SDavid E. O'Brien etracc("exp6 ! cp", cp, vp); 553c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 554c80476e4SDavid E. O'Brien i = egetn(cp); 555c80476e4SDavid E. O'Brien xfree((ptr_t) cp); 556c80476e4SDavid E. O'Brien return (putn(!i)); 557c80476e4SDavid E. O'Brien } 558c80476e4SDavid E. O'Brien if (eq(**vp, STRtilde)) { 559c80476e4SDavid E. O'Brien (*vp)++; 560c80476e4SDavid E. O'Brien cp = exp6(vp, ignore); 561c80476e4SDavid E. O'Brien #ifdef EDEBUG 562c80476e4SDavid E. O'Brien etracc("exp6 ~ cp", cp, vp); 563c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 564c80476e4SDavid E. O'Brien i = egetn(cp); 565c80476e4SDavid E. O'Brien xfree((ptr_t) cp); 566c80476e4SDavid E. O'Brien return (putn(~i)); 567c80476e4SDavid E. O'Brien } 568c80476e4SDavid E. O'Brien if (eq(**vp, STRLparen)) { 569c80476e4SDavid E. O'Brien (*vp)++; 570c80476e4SDavid E. O'Brien ccode = exp0(vp, ignore); 571c80476e4SDavid E. O'Brien #ifdef EDEBUG 572c80476e4SDavid E. O'Brien etraci("exp6 () ccode", ccode, vp); 573c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 574c80476e4SDavid E. O'Brien if (*vp == 0 || **vp == 0 || ***vp != ')') 575c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_EXPRESSION); 576c80476e4SDavid E. O'Brien (*vp)++; 577c80476e4SDavid E. O'Brien return (putn(ccode)); 578c80476e4SDavid E. O'Brien } 579c80476e4SDavid E. O'Brien if (eq(**vp, STRLbrace)) { 580c80476e4SDavid E. O'Brien register Char **v; 581c80476e4SDavid E. O'Brien struct command faket; 582c80476e4SDavid E. O'Brien Char *fakecom[2]; 583c80476e4SDavid E. O'Brien 584c80476e4SDavid E. O'Brien faket.t_dtyp = NODE_COMMAND; 585c80476e4SDavid E. O'Brien faket.t_dflg = F_BACKQ; 586c80476e4SDavid E. O'Brien faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL; 587c80476e4SDavid E. O'Brien faket.t_dcom = fakecom; 588c80476e4SDavid E. O'Brien fakecom[0] = STRfakecom; 589c80476e4SDavid E. O'Brien fakecom[1] = NULL; 590c80476e4SDavid E. O'Brien (*vp)++; 591c80476e4SDavid E. O'Brien v = *vp; 592c80476e4SDavid E. O'Brien for (;;) { 593c80476e4SDavid E. O'Brien if (!**vp) 594c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_MISSING, '}'); 595c80476e4SDavid E. O'Brien if (eq(*(*vp)++, STRRbrace)) 596c80476e4SDavid E. O'Brien break; 597c80476e4SDavid E. O'Brien } 598c80476e4SDavid E. O'Brien if (ignore & TEXP_IGNORE) 599c80476e4SDavid E. O'Brien return (Strsave(STRNULL)); 600c80476e4SDavid E. O'Brien psavejob(); 601c80476e4SDavid E. O'Brien if (pfork(&faket, -1) == 0) { 602c80476e4SDavid E. O'Brien *--(*vp) = 0; 603c80476e4SDavid E. O'Brien evalav(v); 604c80476e4SDavid E. O'Brien exitstat(); 605c80476e4SDavid E. O'Brien } 606c80476e4SDavid E. O'Brien pwait(); 607c80476e4SDavid E. O'Brien prestjob(); 608c80476e4SDavid E. O'Brien #ifdef EDEBUG 609c80476e4SDavid E. O'Brien etraci("exp6 {} status", egetn(varval(STRstatus)), vp); 610c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 611c80476e4SDavid E. O'Brien return (putn(egetn(varval(STRstatus)) == 0)); 612c80476e4SDavid E. O'Brien } 613c80476e4SDavid E. O'Brien if (isa(**vp, ANYOP)) 614c80476e4SDavid E. O'Brien return (Strsave(STRNULL)); 615c80476e4SDavid E. O'Brien cp = *(*vp)++; 616c80476e4SDavid E. O'Brien #ifdef convex 617c80476e4SDavid E. O'Brien # define FILETESTS "erwxfdzoplstSXLbcugkmKR" 618c80476e4SDavid E. O'Brien #else 619c80476e4SDavid E. O'Brien # define FILETESTS "erwxfdzoplstSXLbcugkmK" 620c80476e4SDavid E. O'Brien #endif /* convex */ 621c80476e4SDavid E. O'Brien #define FILEVALS "ZAMCDIUGNFPL" 622c80476e4SDavid E. O'Brien if (*cp == '-' && (any(FILETESTS, cp[1]) || any(FILEVALS, cp[1]))) 623c80476e4SDavid E. O'Brien return(filetest(cp, vp, ignore)); 624c80476e4SDavid E. O'Brien #ifdef EDEBUG 625c80476e4SDavid E. O'Brien etracc("exp6 default", cp, vp); 626c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 627c80476e4SDavid E. O'Brien return (ignore & TEXP_NOGLOB ? Strsave(cp) : globone(cp, G_APPEND)); 628c80476e4SDavid E. O'Brien } 629c80476e4SDavid E. O'Brien 630c80476e4SDavid E. O'Brien 631c80476e4SDavid E. O'Brien /* 632c80476e4SDavid E. O'Brien * Extended file tests 633c80476e4SDavid E. O'Brien * From: John Rowe <rowe@excc.exeter.ac.uk> 634c80476e4SDavid E. O'Brien */ 635c80476e4SDavid E. O'Brien Char * 636c80476e4SDavid E. O'Brien filetest(cp, vp, ignore) 637c80476e4SDavid E. O'Brien Char *cp, ***vp; 638c80476e4SDavid E. O'Brien bool ignore; 639c80476e4SDavid E. O'Brien { 640c80476e4SDavid E. O'Brien #ifdef convex 641c80476e4SDavid E. O'Brien struct cvxstat stb, *st = NULL; 642c80476e4SDavid E. O'Brien # define TCSH_STAT stat64 643c80476e4SDavid E. O'Brien #else 644c80476e4SDavid E. O'Brien # define TCSH_STAT stat 645c80476e4SDavid E. O'Brien struct stat stb, *st = NULL; 646c80476e4SDavid E. O'Brien #endif /* convex */ 647c80476e4SDavid E. O'Brien 648c80476e4SDavid E. O'Brien #ifdef S_IFLNK 649c80476e4SDavid E. O'Brien # ifdef convex 650c80476e4SDavid E. O'Brien struct cvxstat lstb, *lst = NULL; 651c80476e4SDavid E. O'Brien # define TCSH_LSTAT lstat64 652c80476e4SDavid E. O'Brien # else 653c80476e4SDavid E. O'Brien # define TCSH_LSTAT lstat 654c80476e4SDavid E. O'Brien struct stat lstb, *lst = NULL; 655c80476e4SDavid E. O'Brien # endif /* convex */ 656c80476e4SDavid E. O'Brien char *filnam; 657c80476e4SDavid E. O'Brien #endif /* S_IFLNK */ 658c80476e4SDavid E. O'Brien 659c80476e4SDavid E. O'Brien int i = 0; 660c80476e4SDavid E. O'Brien unsigned pmask = 0xffff; 661c80476e4SDavid E. O'Brien bool altout = 0; 662c80476e4SDavid E. O'Brien Char *ft = cp, *dp, *ep, *strdev, *strino, *strF, *str, valtest = '\0', 663c80476e4SDavid E. O'Brien *errval = STR0; 664c80476e4SDavid E. O'Brien char *string, string0[8]; 665c80476e4SDavid E. O'Brien time_t footime; 666c80476e4SDavid E. O'Brien struct passwd *pw; 667c80476e4SDavid E. O'Brien struct group *gr; 668c80476e4SDavid E. O'Brien 669c80476e4SDavid E. O'Brien while(any(FILETESTS, *++ft)) 670c80476e4SDavid E. O'Brien continue; 671c80476e4SDavid E. O'Brien 672c80476e4SDavid E. O'Brien if (!*ft && *(ft - 1) == 'L') 673c80476e4SDavid E. O'Brien --ft; 674c80476e4SDavid E. O'Brien 675c80476e4SDavid E. O'Brien if (any(FILEVALS, *ft)) { 676c80476e4SDavid E. O'Brien valtest = *ft++; 677c80476e4SDavid E. O'Brien /* 678c80476e4SDavid E. O'Brien * Value tests return '-1' on failure as 0 is 679c80476e4SDavid E. O'Brien * a legitimate value for many of them. 680c80476e4SDavid E. O'Brien * 'F' returns ':' for compatibility. 681c80476e4SDavid E. O'Brien */ 682c80476e4SDavid E. O'Brien errval = valtest == 'F' ? STRcolon : STRminus1; 683c80476e4SDavid E. O'Brien 684c80476e4SDavid E. O'Brien if (valtest == 'P' && *ft >= '0' && *ft <= '7') { 685c80476e4SDavid E. O'Brien pmask = (char) *ft - '0'; 686c80476e4SDavid E. O'Brien while ( *++ft >= '0' && *ft <= '7' ) 687c80476e4SDavid E. O'Brien pmask = 8 * pmask + ((char) *ft - '0'); 688c80476e4SDavid E. O'Brien } 689c80476e4SDavid E. O'Brien if (Strcmp(ft, STRcolon) == 0 && any("AMCUGP", valtest)) { 690c80476e4SDavid E. O'Brien altout = 1; 691c80476e4SDavid E. O'Brien ++ft; 692c80476e4SDavid E. O'Brien } 693c80476e4SDavid E. O'Brien } 694c80476e4SDavid E. O'Brien 695c80476e4SDavid E. O'Brien if (*ft || ft == cp + 1) 696c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_FILEINQ); 697c80476e4SDavid E. O'Brien 698c80476e4SDavid E. O'Brien /* 699c80476e4SDavid E. O'Brien * Detect missing file names by checking for operator in the file name 700c80476e4SDavid E. O'Brien * position. However, if an operator name appears there, we must make 701c80476e4SDavid E. O'Brien * sure that there's no file by that name (e.g., "/") before announcing 702c80476e4SDavid E. O'Brien * an error. Even this check isn't quite right, since it doesn't take 703c80476e4SDavid E. O'Brien * globbing into account. 704c80476e4SDavid E. O'Brien */ 705c80476e4SDavid E. O'Brien 706c80476e4SDavid E. O'Brien if (isa(**vp, ANYOP) && TCSH_STAT(short2str(**vp), &stb)) 707c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_FILENAME); 708c80476e4SDavid E. O'Brien 709c80476e4SDavid E. O'Brien dp = *(*vp)++; 710c80476e4SDavid E. O'Brien if (ignore & TEXP_IGNORE) 711c80476e4SDavid E. O'Brien return (Strsave(STRNULL)); 712c80476e4SDavid E. O'Brien ep = globone(dp, G_APPEND); 713c80476e4SDavid E. O'Brien ft = &cp[1]; 714c80476e4SDavid E. O'Brien do 715c80476e4SDavid E. O'Brien switch (*ft) { 716c80476e4SDavid E. O'Brien 717c80476e4SDavid E. O'Brien case 'r': 718c80476e4SDavid E. O'Brien i = !sh_access(ep, R_OK); 719c80476e4SDavid E. O'Brien break; 720c80476e4SDavid E. O'Brien 721c80476e4SDavid E. O'Brien case 'w': 722c80476e4SDavid E. O'Brien i = !sh_access(ep, W_OK); 723c80476e4SDavid E. O'Brien break; 724c80476e4SDavid E. O'Brien 725c80476e4SDavid E. O'Brien case 'x': 726c80476e4SDavid E. O'Brien i = !sh_access(ep, X_OK); 727c80476e4SDavid E. O'Brien break; 728c80476e4SDavid E. O'Brien 729c80476e4SDavid E. O'Brien case 'X': /* tcsh extension, name is an executable in the path 730c80476e4SDavid E. O'Brien * or a tcsh builtin command 731c80476e4SDavid E. O'Brien */ 732c80476e4SDavid E. O'Brien i = find_cmd(ep, 0); 733c80476e4SDavid E. O'Brien break; 734c80476e4SDavid E. O'Brien 735c80476e4SDavid E. O'Brien case 't': /* SGI extension, true when file is a tty */ 736c80476e4SDavid E. O'Brien i = isatty(atoi(short2str(ep))); 737c80476e4SDavid E. O'Brien break; 738c80476e4SDavid E. O'Brien 739c80476e4SDavid E. O'Brien default: 740c80476e4SDavid E. O'Brien 741c80476e4SDavid E. O'Brien #ifdef S_IFLNK 742c80476e4SDavid E. O'Brien if (tolower(*ft) == 'l') { 743c80476e4SDavid E. O'Brien /* 744c80476e4SDavid E. O'Brien * avoid convex compiler bug. 745c80476e4SDavid E. O'Brien */ 746c80476e4SDavid E. O'Brien if (!lst) { 747c80476e4SDavid E. O'Brien lst = &lstb; 748c80476e4SDavid E. O'Brien if (TCSH_LSTAT(short2str(ep), lst) == -1) { 749c80476e4SDavid E. O'Brien xfree((ptr_t) ep); 750c80476e4SDavid E. O'Brien return (Strsave(errval)); 751c80476e4SDavid E. O'Brien } 752c80476e4SDavid E. O'Brien } 753c80476e4SDavid E. O'Brien if (*ft == 'L') 754c80476e4SDavid E. O'Brien st = lst; 755c80476e4SDavid E. O'Brien } 756c80476e4SDavid E. O'Brien else 757c80476e4SDavid E. O'Brien #endif /* S_IFLNK */ 758c80476e4SDavid E. O'Brien /* 759c80476e4SDavid E. O'Brien * avoid convex compiler bug. 760c80476e4SDavid E. O'Brien */ 761c80476e4SDavid E. O'Brien if (!st) { 762c80476e4SDavid E. O'Brien st = &stb; 763c80476e4SDavid E. O'Brien if (TCSH_STAT(short2str(ep), st) == -1) { 764c80476e4SDavid E. O'Brien xfree((ptr_t) ep); 765c80476e4SDavid E. O'Brien return (Strsave(errval)); 766c80476e4SDavid E. O'Brien } 767c80476e4SDavid E. O'Brien } 768c80476e4SDavid E. O'Brien 769c80476e4SDavid E. O'Brien switch (*ft) { 770c80476e4SDavid E. O'Brien 771c80476e4SDavid E. O'Brien case 'f': 772c80476e4SDavid E. O'Brien #ifdef S_ISREG 773c80476e4SDavid E. O'Brien i = S_ISREG(st->st_mode); 774c80476e4SDavid E. O'Brien #else /* !S_ISREG */ 775c80476e4SDavid E. O'Brien i = 0; 776c80476e4SDavid E. O'Brien #endif /* S_ISREG */ 777c80476e4SDavid E. O'Brien break; 778c80476e4SDavid E. O'Brien 779c80476e4SDavid E. O'Brien case 'd': 780c80476e4SDavid E. O'Brien #ifdef S_ISDIR 781c80476e4SDavid E. O'Brien i = S_ISDIR(st->st_mode); 782c80476e4SDavid E. O'Brien #else /* !S_ISDIR */ 783c80476e4SDavid E. O'Brien i = 0; 784c80476e4SDavid E. O'Brien #endif /* S_ISDIR */ 785c80476e4SDavid E. O'Brien break; 786c80476e4SDavid E. O'Brien 787c80476e4SDavid E. O'Brien case 'p': 788c80476e4SDavid E. O'Brien #ifdef S_ISFIFO 789c80476e4SDavid E. O'Brien i = S_ISFIFO(st->st_mode); 790c80476e4SDavid E. O'Brien #else /* !S_ISFIFO */ 791c80476e4SDavid E. O'Brien i = 0; 792c80476e4SDavid E. O'Brien #endif /* S_ISFIFO */ 793c80476e4SDavid E. O'Brien break; 794c80476e4SDavid E. O'Brien 795c80476e4SDavid E. O'Brien case 'm' : 796c80476e4SDavid E. O'Brien #ifdef S_ISOFL 797c80476e4SDavid E. O'Brien i = S_ISOFL(st->st_dm_mode); 798c80476e4SDavid E. O'Brien #else /* !S_ISOFL */ 799c80476e4SDavid E. O'Brien i = 0; 800c80476e4SDavid E. O'Brien #endif /* S_ISOFL */ 801c80476e4SDavid E. O'Brien break ; 802c80476e4SDavid E. O'Brien 803c80476e4SDavid E. O'Brien case 'K' : 804c80476e4SDavid E. O'Brien #ifdef S_ISOFL 805c80476e4SDavid E. O'Brien i = stb.st_dm_key; 806c80476e4SDavid E. O'Brien #else /* !S_ISOFL */ 807c80476e4SDavid E. O'Brien i = 0; 808c80476e4SDavid E. O'Brien #endif /* S_ISOFL */ 809c80476e4SDavid E. O'Brien break ; 810c80476e4SDavid E. O'Brien 811c80476e4SDavid E. O'Brien 812c80476e4SDavid E. O'Brien case 'l': 813c80476e4SDavid E. O'Brien #ifdef S_ISLNK 814c80476e4SDavid E. O'Brien i = S_ISLNK(lst->st_mode); 815c80476e4SDavid E. O'Brien #else /* !S_ISLNK */ 816c80476e4SDavid E. O'Brien i = 0; 817c80476e4SDavid E. O'Brien #endif /* S_ISLNK */ 818c80476e4SDavid E. O'Brien break; 819c80476e4SDavid E. O'Brien 820c80476e4SDavid E. O'Brien case 'S': 821c80476e4SDavid E. O'Brien # ifdef S_ISSOCK 822c80476e4SDavid E. O'Brien i = S_ISSOCK(st->st_mode); 823c80476e4SDavid E. O'Brien # else /* !S_ISSOCK */ 824c80476e4SDavid E. O'Brien i = 0; 825c80476e4SDavid E. O'Brien # endif /* S_ISSOCK */ 826c80476e4SDavid E. O'Brien break; 827c80476e4SDavid E. O'Brien 828c80476e4SDavid E. O'Brien case 'b': 829c80476e4SDavid E. O'Brien #ifdef S_ISBLK 830c80476e4SDavid E. O'Brien i = S_ISBLK(st->st_mode); 831c80476e4SDavid E. O'Brien #else /* !S_ISBLK */ 832c80476e4SDavid E. O'Brien i = 0; 833c80476e4SDavid E. O'Brien #endif /* S_ISBLK */ 834c80476e4SDavid E. O'Brien break; 835c80476e4SDavid E. O'Brien 836c80476e4SDavid E. O'Brien case 'c': 837c80476e4SDavid E. O'Brien #ifdef S_ISCHR 838c80476e4SDavid E. O'Brien i = S_ISCHR(st->st_mode); 839c80476e4SDavid E. O'Brien #else /* !S_ISCHR */ 840c80476e4SDavid E. O'Brien i = 0; 841c80476e4SDavid E. O'Brien #endif /* S_ISCHR */ 842c80476e4SDavid E. O'Brien break; 843c80476e4SDavid E. O'Brien 844c80476e4SDavid E. O'Brien case 'u': 845c80476e4SDavid E. O'Brien i = (S_ISUID & st->st_mode) != 0; 846c80476e4SDavid E. O'Brien break; 847c80476e4SDavid E. O'Brien 848c80476e4SDavid E. O'Brien case 'g': 849c80476e4SDavid E. O'Brien i = (S_ISGID & st->st_mode) != 0; 850c80476e4SDavid E. O'Brien break; 851c80476e4SDavid E. O'Brien 852c80476e4SDavid E. O'Brien case 'k': 853c80476e4SDavid E. O'Brien i = (S_ISVTX & st->st_mode) != 0; 854c80476e4SDavid E. O'Brien break; 855c80476e4SDavid E. O'Brien 856c80476e4SDavid E. O'Brien case 'z': 857c80476e4SDavid E. O'Brien i = st->st_size == 0; 858c80476e4SDavid E. O'Brien break; 859c80476e4SDavid E. O'Brien 860c80476e4SDavid E. O'Brien #ifdef convex 861c80476e4SDavid E. O'Brien case 'R': 862c80476e4SDavid E. O'Brien i = (stb.st_dmonflags & IMIGRATED) == IMIGRATED; 863c80476e4SDavid E. O'Brien break; 864c80476e4SDavid E. O'Brien #endif /* convex */ 865c80476e4SDavid E. O'Brien 866c80476e4SDavid E. O'Brien case 's': 867c80476e4SDavid E. O'Brien i = stb.st_size != 0; 868c80476e4SDavid E. O'Brien break; 869c80476e4SDavid E. O'Brien 870c80476e4SDavid E. O'Brien case 'e': 871c80476e4SDavid E. O'Brien i = 1; 872c80476e4SDavid E. O'Brien break; 873c80476e4SDavid E. O'Brien 874c80476e4SDavid E. O'Brien case 'o': 875c80476e4SDavid E. O'Brien i = st->st_uid == uid; 876c80476e4SDavid E. O'Brien break; 877c80476e4SDavid E. O'Brien 878c80476e4SDavid E. O'Brien /* 879c80476e4SDavid E. O'Brien * Value operators are a tcsh extension. 880c80476e4SDavid E. O'Brien */ 881c80476e4SDavid E. O'Brien 882c80476e4SDavid E. O'Brien case 'D': 883c80476e4SDavid E. O'Brien i = (int) st->st_dev; 884c80476e4SDavid E. O'Brien break; 885c80476e4SDavid E. O'Brien 886c80476e4SDavid E. O'Brien case 'I': 887c80476e4SDavid E. O'Brien i = (int) st->st_ino; 888c80476e4SDavid E. O'Brien break; 889c80476e4SDavid E. O'Brien 890c80476e4SDavid E. O'Brien case 'F': 891c80476e4SDavid E. O'Brien strdev = putn( (int) st->st_dev); 892c80476e4SDavid E. O'Brien strino = putn( (int) st->st_ino); 893c80476e4SDavid E. O'Brien strF = (Char *) xmalloc((size_t) (2 + Strlen(strdev) + 894c80476e4SDavid E. O'Brien Strlen(strino)) * sizeof(Char)); 895c80476e4SDavid E. O'Brien (void) Strcat(Strcat(Strcpy(strF, strdev), STRcolon), strino); 896c80476e4SDavid E. O'Brien xfree((ptr_t) strdev); 897c80476e4SDavid E. O'Brien xfree((ptr_t) strino); 898c80476e4SDavid E. O'Brien xfree((ptr_t) ep); 899c80476e4SDavid E. O'Brien return(strF); 900c80476e4SDavid E. O'Brien 901c80476e4SDavid E. O'Brien case 'L': 902c80476e4SDavid E. O'Brien if ( *(ft + 1) ) { 903c80476e4SDavid E. O'Brien i = 1; 904c80476e4SDavid E. O'Brien break; 905c80476e4SDavid E. O'Brien } 906c80476e4SDavid E. O'Brien #ifdef S_ISLNK 907c80476e4SDavid E. O'Brien filnam = short2str(ep); 908c80476e4SDavid E. O'Brien #ifdef PATH_MAX 909c80476e4SDavid E. O'Brien # define MY_PATH_MAX PATH_MAX 910c80476e4SDavid E. O'Brien #else /* !PATH_MAX */ 911c80476e4SDavid E. O'Brien /* 912c80476e4SDavid E. O'Brien * I can't think of any more sensible alterative; readlink doesn't give 913c80476e4SDavid E. O'Brien * us an errno if the buffer isn't large enough :-( 914c80476e4SDavid E. O'Brien */ 915c80476e4SDavid E. O'Brien # define MY_PATH_MAX 2048 916c80476e4SDavid E. O'Brien #endif /* PATH_MAX */ 917c80476e4SDavid E. O'Brien i = readlink(filnam, string = (char *) 918c80476e4SDavid E. O'Brien xmalloc((size_t) (1 + MY_PATH_MAX) * sizeof(char)), 919c80476e4SDavid E. O'Brien MY_PATH_MAX); 920c80476e4SDavid E. O'Brien if (i >= 0 && i <= MY_PATH_MAX) 921c80476e4SDavid E. O'Brien string[i] = '\0'; /* readlink does not null terminate */ 922c80476e4SDavid E. O'Brien strF = (i < 0) ? errval : str2short(string); 923c80476e4SDavid E. O'Brien xfree((ptr_t) string); 924c80476e4SDavid E. O'Brien xfree((ptr_t) ep); 925c80476e4SDavid E. O'Brien return(Strsave(strF)); 926c80476e4SDavid E. O'Brien 927c80476e4SDavid E. O'Brien #else /* !S_ISLNK */ 928c80476e4SDavid E. O'Brien i = 0; 929c80476e4SDavid E. O'Brien break; 930c80476e4SDavid E. O'Brien #endif /* S_ISLNK */ 931c80476e4SDavid E. O'Brien 932c80476e4SDavid E. O'Brien 933c80476e4SDavid E. O'Brien case 'N': 934c80476e4SDavid E. O'Brien i = (int) st->st_nlink; 935c80476e4SDavid E. O'Brien break; 936c80476e4SDavid E. O'Brien 937c80476e4SDavid E. O'Brien case 'P': 938c80476e4SDavid E. O'Brien string = string0 + 1; 939c80476e4SDavid E. O'Brien (void) xsnprintf(string, sizeof(string0) - 1, "%o", 940c80476e4SDavid E. O'Brien pmask & (unsigned int) 941c80476e4SDavid E. O'Brien ((S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID) & st->st_mode)); 942c80476e4SDavid E. O'Brien if (altout && *string != '0') 943c80476e4SDavid E. O'Brien *--string = '0'; 944c80476e4SDavid E. O'Brien xfree((ptr_t) ep); 945c80476e4SDavid E. O'Brien return(Strsave(str2short(string))); 946c80476e4SDavid E. O'Brien 947c80476e4SDavid E. O'Brien case 'U': 948c80476e4SDavid E. O'Brien if (altout && (pw = getpwuid(st->st_uid))) { 949c80476e4SDavid E. O'Brien xfree((ptr_t) ep); 950c80476e4SDavid E. O'Brien return(Strsave(str2short(pw->pw_name))); 951c80476e4SDavid E. O'Brien } 952c80476e4SDavid E. O'Brien i = (int) st->st_uid; 953c80476e4SDavid E. O'Brien break; 954c80476e4SDavid E. O'Brien 955c80476e4SDavid E. O'Brien case 'G': 956c80476e4SDavid E. O'Brien if ( altout && (gr = getgrgid(st->st_gid))) { 957c80476e4SDavid E. O'Brien xfree((ptr_t) ep); 958c80476e4SDavid E. O'Brien return(Strsave(str2short(gr->gr_name))); 959c80476e4SDavid E. O'Brien } 960c80476e4SDavid E. O'Brien i = (int) st->st_gid; 961c80476e4SDavid E. O'Brien break; 962c80476e4SDavid E. O'Brien 963c80476e4SDavid E. O'Brien case 'Z': 964c80476e4SDavid E. O'Brien i = (int) st->st_size; 965c80476e4SDavid E. O'Brien break; 966c80476e4SDavid E. O'Brien 967c80476e4SDavid E. O'Brien case 'A': case 'M': case 'C': 968c80476e4SDavid E. O'Brien footime = *ft == 'A' ? st->st_atime : 969c80476e4SDavid E. O'Brien *ft == 'M' ? st->st_mtime : st->st_ctime; 970c80476e4SDavid E. O'Brien if (altout) { 971c80476e4SDavid E. O'Brien strF = str2short(ctime(&footime)); 972c80476e4SDavid E. O'Brien if ((str = Strchr(strF, '\n')) != NULL) 973c80476e4SDavid E. O'Brien *str = (Char) '\0'; 974c80476e4SDavid E. O'Brien xfree((ptr_t) ep); 975c80476e4SDavid E. O'Brien return(Strsave(strF)); 976c80476e4SDavid E. O'Brien } 977c80476e4SDavid E. O'Brien i = (int) footime; 978c80476e4SDavid E. O'Brien break; 979c80476e4SDavid E. O'Brien 980c80476e4SDavid E. O'Brien } 981c80476e4SDavid E. O'Brien } 982c80476e4SDavid E. O'Brien while (*++ft && i); 983c80476e4SDavid E. O'Brien #ifdef EDEBUG 984c80476e4SDavid E. O'Brien etraci("exp6 -? i", i, vp); 985c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 986c80476e4SDavid E. O'Brien xfree((ptr_t) ep); 987c80476e4SDavid E. O'Brien return (putn(i)); 988c80476e4SDavid E. O'Brien } 989c80476e4SDavid E. O'Brien 990c80476e4SDavid E. O'Brien 991c80476e4SDavid E. O'Brien static void 992c80476e4SDavid E. O'Brien evalav(v) 993c80476e4SDavid E. O'Brien register Char **v; 994c80476e4SDavid E. O'Brien { 995c80476e4SDavid E. O'Brien struct wordent paraml1; 996c80476e4SDavid E. O'Brien register struct wordent *hp = ¶ml1; 997c80476e4SDavid E. O'Brien struct command *t; 998c80476e4SDavid E. O'Brien register struct wordent *wdp = hp; 999c80476e4SDavid E. O'Brien 1000c80476e4SDavid E. O'Brien set(STRstatus, Strsave(STR0), VAR_READWRITE); 1001c80476e4SDavid E. O'Brien hp->prev = hp->next = hp; 1002c80476e4SDavid E. O'Brien hp->word = STRNULL; 1003c80476e4SDavid E. O'Brien while (*v) { 1004c80476e4SDavid E. O'Brien register struct wordent *new = 1005c80476e4SDavid E. O'Brien (struct wordent *) xcalloc(1, sizeof *wdp); 1006c80476e4SDavid E. O'Brien 1007c80476e4SDavid E. O'Brien new->prev = wdp; 1008c80476e4SDavid E. O'Brien new->next = hp; 1009c80476e4SDavid E. O'Brien wdp->next = new; 1010c80476e4SDavid E. O'Brien wdp = new; 1011c80476e4SDavid E. O'Brien wdp->word = Strsave(*v++); 1012c80476e4SDavid E. O'Brien } 1013c80476e4SDavid E. O'Brien hp->prev = wdp; 1014c80476e4SDavid E. O'Brien alias(¶ml1); 1015c80476e4SDavid E. O'Brien t = syntax(paraml1.next, ¶ml1, 0); 1016c80476e4SDavid E. O'Brien if (seterr) 1017c80476e4SDavid E. O'Brien stderror(ERR_OLD); 101829301572SMark Peek execute(t, -1, NULL, NULL, TRUE); 1019c80476e4SDavid E. O'Brien freelex(¶ml1), freesyn(t); 1020c80476e4SDavid E. O'Brien } 1021c80476e4SDavid E. O'Brien 1022c80476e4SDavid E. O'Brien static int 1023c80476e4SDavid E. O'Brien isa(cp, what) 1024c80476e4SDavid E. O'Brien register Char *cp; 1025c80476e4SDavid E. O'Brien register int what; 1026c80476e4SDavid E. O'Brien { 1027c80476e4SDavid E. O'Brien if (cp == 0) 1028c80476e4SDavid E. O'Brien return ((what & RESTOP) != 0); 1029c80476e4SDavid E. O'Brien if (*cp == '\0') 1030c80476e4SDavid E. O'Brien return 0; 1031c80476e4SDavid E. O'Brien if (cp[1] == 0) { 1032c80476e4SDavid E. O'Brien if (what & ADDOP && (*cp == '+' || *cp == '-')) 1033c80476e4SDavid E. O'Brien return (1); 1034c80476e4SDavid E. O'Brien if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%')) 1035c80476e4SDavid E. O'Brien return (1); 1036c80476e4SDavid E. O'Brien if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' || 1037c80476e4SDavid E. O'Brien *cp == '~' || *cp == '^' || *cp == '"')) 1038c80476e4SDavid E. O'Brien return (1); 1039c80476e4SDavid E. O'Brien } 1040c80476e4SDavid E. O'Brien else if (cp[2] == 0) { 1041c80476e4SDavid E. O'Brien if (what & RESTOP) { 1042c80476e4SDavid E. O'Brien if (cp[0] == '|' && cp[1] == '&') 1043c80476e4SDavid E. O'Brien return (1); 1044c80476e4SDavid E. O'Brien if (cp[0] == '<' && cp[1] == '<') 1045c80476e4SDavid E. O'Brien return (1); 1046c80476e4SDavid E. O'Brien if (cp[0] == '>' && cp[1] == '>') 1047c80476e4SDavid E. O'Brien return (1); 1048c80476e4SDavid E. O'Brien } 1049c80476e4SDavid E. O'Brien if (what & EQOP) { 1050c80476e4SDavid E. O'Brien if (cp[0] == '=') { 1051c80476e4SDavid E. O'Brien if (cp[1] == '=') 1052c80476e4SDavid E. O'Brien return (EQEQ); 1053c80476e4SDavid E. O'Brien if (cp[1] == '~') 1054c80476e4SDavid E. O'Brien return (EQMATCH); 1055c80476e4SDavid E. O'Brien } 1056c80476e4SDavid E. O'Brien else if (cp[0] == '!') { 1057c80476e4SDavid E. O'Brien if (cp[1] == '=') 1058c80476e4SDavid E. O'Brien return (NOTEQ); 1059c80476e4SDavid E. O'Brien if (cp[1] == '~') 1060c80476e4SDavid E. O'Brien return (NOTEQMATCH); 1061c80476e4SDavid E. O'Brien } 1062c80476e4SDavid E. O'Brien } 1063c80476e4SDavid E. O'Brien } 1064c80476e4SDavid E. O'Brien if (what & RELOP) { 1065c80476e4SDavid E. O'Brien if (*cp == '<') 1066c80476e4SDavid E. O'Brien return (LSS); 1067c80476e4SDavid E. O'Brien if (*cp == '>') 1068c80476e4SDavid E. O'Brien return (GTR); 1069c80476e4SDavid E. O'Brien } 1070c80476e4SDavid E. O'Brien return (0); 1071c80476e4SDavid E. O'Brien } 1072c80476e4SDavid E. O'Brien 1073c80476e4SDavid E. O'Brien static int 1074c80476e4SDavid E. O'Brien egetn(cp) 1075c80476e4SDavid E. O'Brien register Char *cp; 1076c80476e4SDavid E. O'Brien { 1077c80476e4SDavid E. O'Brien if (*cp && *cp != '-' && !Isdigit(*cp)) 1078c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_EXPRESSION); 1079c80476e4SDavid E. O'Brien return (getn(cp)); 1080c80476e4SDavid E. O'Brien } 1081c80476e4SDavid E. O'Brien 1082c80476e4SDavid E. O'Brien /* Phew! */ 1083c80476e4SDavid E. O'Brien 1084c80476e4SDavid E. O'Brien #ifdef EDEBUG 1085c80476e4SDavid E. O'Brien static void 1086c80476e4SDavid E. O'Brien etraci(str, i, vp) 1087c80476e4SDavid E. O'Brien char *str; 1088c80476e4SDavid E. O'Brien int i; 1089c80476e4SDavid E. O'Brien Char ***vp; 1090c80476e4SDavid E. O'Brien { 1091c80476e4SDavid E. O'Brien xprintf("%s=%d\t", str, i); 1092c80476e4SDavid E. O'Brien blkpr(*vp); 1093c80476e4SDavid E. O'Brien xputchar('\n'); 1094c80476e4SDavid E. O'Brien } 1095c80476e4SDavid E. O'Brien static void 1096c80476e4SDavid E. O'Brien etracc(str, cp, vp) 1097c80476e4SDavid E. O'Brien char *str; 1098c80476e4SDavid E. O'Brien Char *cp; 1099c80476e4SDavid E. O'Brien Char ***vp; 1100c80476e4SDavid E. O'Brien { 1101c80476e4SDavid E. O'Brien xprintf("%s=%s\t", str, cp); 1102c80476e4SDavid E. O'Brien blkpr(*vp); 1103c80476e4SDavid E. O'Brien xputchar('\n'); 1104c80476e4SDavid E. O'Brien } 1105c80476e4SDavid E. O'Brien #endif /* EDEBUG */ 1106