1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.misc.c,v 3.2 1991/07/05 02:23:28 christos Exp $ */ 2: /* 3: * sh.misc.c: Miscelaneous functions 4: */ 5: /*- 6: * Copyright (c) 1980, 1991 The Regents of the University of California. 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by the University of 20: * California, Berkeley and its contributors. 21: * 4. Neither the name of the University nor the names of its contributors 22: * may be used to endorse or promote products derived from this software 23: * without specific prior written permission. 24: * 25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35: * SUCH DAMAGE. 36: */ 37: #include "config.h" 38: #if !defined(lint) && !defined(pdp11) 39: static char *rcsid() 40: { return "$Id: sh.misc.c,v 3.2 1991/07/05 02:23:28 christos Exp $"; } 41: #endif 42: 43: #include "sh.h" 44: 45: static int renum __P((int, int)); 46: 47: /* 48: * C Shell 49: */ 50: 51: int 52: any(s, c) 53: register char *s; 54: register int c; 55: { 56: if (!s) 57: return (0); /* Check for nil pointer */ 58: while (*s) 59: if (*s++ == c) 60: return (1); 61: return (0); 62: } 63: 64: void 65: setzero(cp, i) 66: char *cp; 67: int i; 68: { 69: if (i != 0) 70: do 71: *cp++ = 0; 72: while (--i); 73: } 74: 75: char * 76: strsave(s) 77: register char *s; 78: { 79: char *n; 80: register char *p; 81: 82: if (s == 0) 83: s = ""; 84: for (p = s; *p++;); 85: n = p = (char *) xmalloc((size_t) ((p - s) * sizeof(char))); 86: while (*p++ = *s++); 87: return (n); 88: } 89: 90: Char ** 91: blkend(up) 92: register Char **up; 93: { 94: 95: while (*up) 96: up++; 97: return (up); 98: } 99: 100: 101: void 102: blkpr(av) 103: register Char **av; 104: { 105: 106: for (; *av; av++) { 107: xprintf("%s", short2str(*av)); 108: if (av[1]) 109: xprintf(" "); 110: } 111: } 112: 113: int 114: blklen(av) 115: register Char **av; 116: { 117: register int i = 0; 118: 119: while (*av++) 120: i++; 121: return (i); 122: } 123: 124: Char ** 125: blkcpy(oav, bv) 126: Char **oav; 127: register Char **bv; 128: { 129: register Char **av = oav; 130: 131: while (*av++ = *bv++) 132: continue; 133: return (oav); 134: } 135: 136: Char ** 137: blkcat(up, vp) 138: Char **up, **vp; 139: { 140: 141: (void) blkcpy(blkend(up), vp); 142: return (up); 143: } 144: 145: void 146: blkfree(av0) 147: Char **av0; 148: { 149: register Char **av = av0; 150: 151: if (!av0) 152: return; 153: for (; *av; av++) 154: xfree((ptr_t) * av); 155: xfree((ptr_t) av0); 156: } 157: 158: Char ** 159: saveblk(v) 160: register Char **v; 161: { 162: register Char **newv = 163: (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 164: Char **onewv = newv; 165: 166: while (*v) 167: *newv++ = Strsave(*v++); 168: return (onewv); 169: } 170: 171: #ifndef POSIX 172: char * 173: strstr(s, t) 174: register const char *s, *t; 175: { 176: do { 177: register const char *ss = s; 178: register const char *tt = t; 179: 180: do 181: if (*tt == '\0') 182: return ((char *) s); 183: while (*ss++ == *tt++); 184: } while (*s++ != '\0'); 185: return (NULL); 186: } 187: 188: #endif /* POSIX */ 189: 190: #ifndef SHORT_STRINGS 191: char * 192: strspl(cp, dp) 193: char *cp, *dp; 194: { 195: char *ep; 196: register char *p, *q; 197: 198: if (!cp) 199: cp = ""; 200: if (!dp) 201: dp = ""; 202: for (p = cp; *p++;); 203: for (q = dp; *q++;); 204: ep = (char *) xmalloc((size_t) (((p - cp) + (q - dp) - 1) * sizeof(char))); 205: for (p = ep, q = cp; *p++ = *q++;); 206: for (p--, q = dp; *p++ = *q++;); 207: return (ep); 208: } 209: 210: #endif 211: 212: Char ** 213: blkspl(up, vp) 214: register Char **up, **vp; 215: { 216: register Char **wp = 217: (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1), 218: sizeof(Char **)); 219: 220: (void) blkcpy(wp, up); 221: return (blkcat(wp, vp)); 222: } 223: 224: Char 225: lastchr(cp) 226: register Char *cp; 227: { 228: 229: if (!cp) 230: return (0); 231: if (!*cp) 232: return (0); 233: while (cp[1]) 234: cp++; 235: return (*cp); 236: } 237: 238: /* 239: * This routine is called after an error to close up 240: * any units which may have been left open accidentally. 241: */ 242: void 243: closem() 244: { 245: register int f; 246: 247: #ifdef YPBUGS 248: /* suggested by Justin Bur; thanks to Karl Kleinpaste */ 249: fix_yp_bugs(); 250: #endif 251: for (f = 0; f < NOFILE; f++) 252: if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD && 253: f != FSHTTY) 254: (void) close(f); 255: } 256: 257: #ifndef FIOCLEX 258: /* 259: * Close files before executing a file. 260: * We could be MUCH more intelligent, since (on a version 7 system) 261: * we need only close files here during a source, the other 262: * shell fd's being in units 16-19 which are closed automatically! 263: */ 264: void 265: closech() 266: { 267: register int f; 268: 269: if (didcch) 270: return; 271: didcch = 1; 272: SHIN = 0; 273: SHOUT = 1; 274: SHDIAG = 2; 275: OLDSTD = 0; 276: isoutatty = isatty(SHOUT); 277: isdiagatty = isatty(SHDIAG); 278: for (f = 3; f < NOFILE; f++) 279: (void) close(f); 280: } 281: 282: #endif 283: 284: void 285: donefds() 286: { 287: 288: (void) close(0); 289: (void) close(1); 290: (void) close(2); 291: didfds = 0; 292: } 293: 294: /* 295: * Move descriptor i to j. 296: * If j is -1 then we just want to get i to a safe place, 297: * i.e. to a unit > 2. This also happens in dcopy. 298: */ 299: int 300: dmove(i, j) 301: register int i, j; 302: { 303: 304: if (i == j || i < 0) 305: return (i); 306: #ifdef DUP2 307: if (j >= 0) { 308: (void) dup2(i, j); 309: if (j != i) 310: (void) close(i); 311: return (j); 312: } 313: #endif 314: j = dcopy(i, j); 315: if (j != i) 316: (void) close(i); 317: return (j); 318: } 319: 320: int 321: dcopy(i, j) 322: register int i, j; 323: { 324: 325: if (i == j || i < 0 || j < 0 && i > 2) 326: return (i); 327: #ifdef DUP2 328: if (j >= 0) { 329: (void) dup2(i, j); 330: return (j); 331: } 332: #endif 333: (void) close(j); 334: return (renum(i, j)); 335: } 336: 337: static int 338: renum(i, j) 339: register int i, j; 340: { 341: register int k = dup(i); 342: 343: if (k < 0) 344: return (-1); 345: if (j == -1 && k > 2) 346: return (k); 347: if (k != j) { 348: j = renum(k, j); 349: (void) close(k); 350: return (j); 351: } 352: return (k); 353: } 354: 355: void 356: copy(to, from, size) 357: register char *to, *from; 358: register int size; 359: { 360: 361: if (size && from && to) 362: do 363: *to++ = *from++; 364: while (--size != 0); 365: } 366: 367: /* 368: * Left shift a command argument list, discarding 369: * the first c arguments. Used in "shift" commands 370: * as well as by commands like "repeat". 371: */ 372: void 373: lshift(v, c) 374: register Char **v; 375: register int c; 376: { 377: register Char **u = v; 378: 379: while (*u && --c >= 0) 380: xfree((ptr_t) * u++); 381: (void) blkcpy(v, u); 382: } 383: 384: int 385: number(cp) 386: Char *cp; 387: { 388: if (!cp) 389: return (0); 390: if (*cp == '-') { 391: cp++; 392: if (!Isdigit(*cp)) 393: return (0); 394: cp++; 395: } 396: while (*cp && Isdigit(*cp)) 397: cp++; 398: return (*cp == 0); 399: } 400: 401: Char ** 402: copyblk(v) 403: register Char **v; 404: { 405: register Char **nv = 406: (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 407: 408: return (blkcpy(nv, v)); 409: } 410: 411: #ifndef SHORT_STRINGS 412: char * 413: strend(cp) 414: register char *cp; 415: { 416: if (!cp) 417: return (cp); 418: while (*cp) 419: cp++; 420: return (cp); 421: } 422: 423: #endif /* SHORT_STRINGS */ 424: 425: Char * 426: strip(cp) 427: Char *cp; 428: { 429: register Char *dp = cp; 430: 431: if (!cp) 432: return (cp); 433: while (*dp++ &= TRIM) 434: continue; 435: return (cp); 436: } 437: 438: void 439: udvar(name) 440: Char *name; 441: { 442: 443: setname(short2str(name)); 444: stderror(ERR_NAME | ERR_UNDVAR); 445: } 446: 447: int 448: prefix(sub, str) 449: register Char *sub, *str; 450: { 451: 452: for (;;) { 453: if (*sub == 0) 454: return (1); 455: if (*str == 0) 456: return (0); 457: if (*sub++ != *str++) 458: return (0); 459: } 460: }