sh.misc.c revision 131962
1117845Ssam/* $Header: /src/pub/tcsh/sh.misc.c,v 3.26 2003/03/12 19:14:51 christos Exp $ */ 2117845Ssam/* 3117845Ssam * sh.misc.c: Miscelaneous functions 4117845Ssam */ 5117845Ssam/*- 6117845Ssam * Copyright (c) 1980, 1991 The Regents of the University of California. 7117845Ssam * All rights reserved. 8117845Ssam * 9117845Ssam * Redistribution and use in source and binary forms, with or without 10117845Ssam * modification, are permitted provided that the following conditions 11117845Ssam * are met: 12117845Ssam * 1. Redistributions of source code must retain the above copyright 13117845Ssam * notice, this list of conditions and the following disclaimer. 14117845Ssam * 2. Redistributions in binary form must reproduce the above copyright 15117845Ssam * notice, this list of conditions and the following disclaimer in the 16117845Ssam * documentation and/or other materials provided with the distribution. 17117845Ssam * 3. Neither the name of the University nor the names of its contributors 18117845Ssam * may be used to endorse or promote products derived from this software 19117845Ssam * without specific prior written permission. 20117845Ssam * 21117845Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22117845Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23117845Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24117845Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25117845Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26117845Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27117845Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28117845Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29117845Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30117845Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31117845Ssam * SUCH DAMAGE. 32117845Ssam */ 33117845Ssam#include "sh.h" 34117845Ssam 35117845SsamRCSID("$Id: sh.misc.c,v 3.26 2003/03/12 19:14:51 christos Exp $") 36117845Ssam 37117845Ssamstatic int renum __P((int, int)); 38117845Ssamstatic Char **blkend __P((Char **)); 39117845Ssamstatic Char **blkcat __P((Char **, Char **)); 40117845Ssam 41117845Ssam/* 42117845Ssam * C Shell 43117845Ssam */ 44117845Ssam 45117845Ssamint 46117845Ssamany(s, c) 47117845Ssam register char *s; 48117845Ssam register int c; 49117845Ssam{ 50117845Ssam if (!s) 51117845Ssam return (0); /* Check for nil pointer */ 52117845Ssam while (*s) 53117845Ssam if (*s++ == c) 54117845Ssam return (1); 55117845Ssam return (0); 56117845Ssam} 57117845Ssam 58117845Ssamvoid 59117845Ssamsetzero(cp, i) 60117845Ssam char *cp; 61117845Ssam int i; 62117845Ssam{ 63117845Ssam if (i != 0) 64117845Ssam do 65117845Ssam *cp++ = 0; 66117845Ssam while (--i); 67117845Ssam} 68117845Ssam 69117845Ssamchar * 70117845Ssamstrsave(s) 71117845Ssam register const char *s; 72117845Ssam{ 73117845Ssam char *n; 74117845Ssam register char *p; 75117845Ssam 76117845Ssam if (s == NULL) 77117845Ssam s = (const char *) ""; 78117845Ssam for (p = (char *) s; *p++ != '\0';) 79117845Ssam continue; 80117845Ssam n = p = (char *) xmalloc((size_t) 81117845Ssam ((((const char *) p) - s) * sizeof(char))); 82117845Ssam while ((*p++ = *s++) != '\0') 83117845Ssam continue; 84117845Ssam return (n); 85117845Ssam} 86117845Ssam 87117845Ssamstatic Char ** 88117845Ssamblkend(up) 89117845Ssam register Char **up; 90117845Ssam{ 91117845Ssam 92117845Ssam while (*up) 93117845Ssam up++; 94117845Ssam return (up); 95117845Ssam} 96117845Ssam 97117845Ssam 98117845Ssamvoid 99117845Ssamblkpr(av) 100117845Ssam register Char **av; 101117845Ssam{ 102117845Ssam 103117845Ssam for (; *av; av++) { 104117845Ssam xprintf("%S", *av); 105117845Ssam if (av[1]) 106117845Ssam xprintf(" "); 107117845Ssam } 108117845Ssam} 109117845Ssam 110117845Ssamvoid 111117845Ssamblkexpand(av, str) 112117845Ssam register Char **av; 113117845Ssam Char *str; 114117845Ssam{ 115117845Ssam *str = '\0'; 116117845Ssam for (; *av; av++) { 117117845Ssam (void) Strcat(str, *av); 118117845Ssam if (av[1]) 119117845Ssam (void) Strcat(str, STRspace); 120117845Ssam } 121117845Ssam} 122117845Ssam 123117845Ssamint 124117845Ssamblklen(av) 125117845Ssam register Char **av; 126117845Ssam{ 127117845Ssam register int i = 0; 128117845Ssam 129117845Ssam while (*av++) 130117845Ssam i++; 131117845Ssam return (i); 132117845Ssam} 133117845Ssam 134117845SsamChar ** 135117845Ssamblkcpy(oav, bv) 136117845Ssam Char **oav; 137117845Ssam register Char **bv; 138117845Ssam{ 139117845Ssam register Char **av = oav; 140117845Ssam 141117845Ssam while ((*av++ = *bv++) != NULL) 142117845Ssam continue; 143117845Ssam return (oav); 144117845Ssam} 145117845Ssam 146117845Ssamstatic Char ** 147117845Ssamblkcat(up, vp) 148117845Ssam Char **up, **vp; 149117845Ssam{ 150117845Ssam 151117845Ssam (void) blkcpy(blkend(up), vp); 152117845Ssam return (up); 153117845Ssam} 154117845Ssam 155117845Ssamvoid 156117845Ssamblkfree(av0) 157117845Ssam Char **av0; 158117845Ssam{ 159117845Ssam register Char **av = av0; 160117845Ssam 161117845Ssam if (!av0) 162117845Ssam return; 163117845Ssam for (; *av; av++) 164117845Ssam xfree((ptr_t) * av); 165117845Ssam xfree((ptr_t) av0); 166117845Ssam} 167117845Ssam 168117845SsamChar ** 169117845Ssamsaveblk(v) 170117845Ssam register Char **v; 171117845Ssam{ 172117845Ssam register Char **newv = 173117845Ssam (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 174117845Ssam Char **onewv = newv; 175117845Ssam 176117845Ssam while (*v) 177117845Ssam *newv++ = Strsave(*v++); 178117845Ssam return (onewv); 179117845Ssam} 180117845Ssam 181117845Ssam#if !defined(SHORT_STRINGS) && !defined(POSIX) 182117845Ssamchar * 183117845Ssamstrstr(s, t) 184117845Ssam register const char *s, *t; 185117845Ssam{ 186117845Ssam do { 187117845Ssam register const char *ss = s; 188117845Ssam register const char *tt = t; 189117845Ssam 190117845Ssam do 191117845Ssam if (*tt == '\0') 192117845Ssam return ((char *) s); 193117845Ssam while (*ss++ == *tt++); 194117845Ssam } while (*s++ != '\0'); 195117845Ssam return (NULL); 196117845Ssam} 197117845Ssam 198117845Ssam#endif /* !SHORT_STRINGS && !POSIX */ 199117845Ssam 200117845Ssam#ifndef SHORT_STRINGS 201117845Ssamchar * 202117845Ssamstrspl(cp, dp) 203117845Ssam char *cp, *dp; 204117845Ssam{ 205117845Ssam char *ep; 206117845Ssam register char *p, *q; 207117845Ssam 208117845Ssam if (!cp) 209117845Ssam cp = ""; 210117845Ssam if (!dp) 211117845Ssam dp = ""; 212117845Ssam for (p = cp; *p++ != '\0';) 213117845Ssam continue; 214117845Ssam for (q = dp; *q++ != '\0';) 215117845Ssam continue; 216117845Ssam ep = (char *) xmalloc((size_t) (((p - cp) + (q - dp) - 1) * sizeof(char))); 217117845Ssam for (p = ep, q = cp; (*p++ = *q++) != '\0';) 218117845Ssam continue; 219117845Ssam for (p--, q = dp; (*p++ = *q++) != '\0';) 220117845Ssam continue; 221117845Ssam return (ep); 222117845Ssam} 223117845Ssam 224117845Ssam#endif /* !SHORT_STRINGS */ 225117845Ssam 226117845SsamChar ** 227117845Ssamblkspl(up, vp) 228117845Ssam register Char **up, **vp; 229117845Ssam{ 230117845Ssam register Char **wp = 231117845Ssam (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1), 232117845Ssam sizeof(Char **)); 233117845Ssam 234117845Ssam (void) blkcpy(wp, up); 235117845Ssam return (blkcat(wp, vp)); 236117845Ssam} 237117845Ssam 238117845SsamChar 239117845Ssamlastchr(cp) 240117845Ssam register Char *cp; 241117845Ssam{ 242117845Ssam 243117845Ssam if (!cp) 244117845Ssam return (0); 245117845Ssam if (!*cp) 246117845Ssam return (0); 247117845Ssam while (cp[1]) 248117845Ssam cp++; 249117845Ssam return (*cp); 250117845Ssam} 251117845Ssam 252117845Ssam/* 253117845Ssam * This routine is called after an error to close up 254117845Ssam * any units which may have been left open accidentally. 255117845Ssam */ 256117845Ssamvoid 257117845Ssamclosem() 258117845Ssam{ 259117845Ssam register int f; 260117845Ssam 261117845Ssam#ifdef NLS_BUGS 262117845Ssam#ifdef NLS_CATALOGS 263117845Ssam (void)catclose(catd); 264117845Ssam#endif /* NLS_CATALOGS */ 265117845Ssam#endif /* NLS_BUGS */ 266117845Ssam#ifdef YPBUGS 267117845Ssam /* suggested by Justin Bur; thanks to Karl Kleinpaste */ 268117845Ssam fix_yp_bugs(); 269117845Ssam#endif /* YPBUGS */ 270117845Ssam for (f = 0; f < NOFILE; f++) 271117845Ssam if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD && 272117845Ssam f != FSHTTY 273117845Ssam#ifdef MALLOC_TRACE 274117845Ssam && f != 25 275117845Ssam#endif /* MALLOC_TRACE */ 276117845Ssam ) 277117845Ssam { 278117845Ssam (void) close(f); 279117845Ssam#ifdef NISPLUS 280117845Ssam if(f < 3) 281117845Ssam (void) open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 282117845Ssam#endif /* NISPLUS */ 283117845Ssam } 284117845Ssam#ifdef NLS_BUGS 285117845Ssam#ifdef NLS_CATALOGS 286117845Ssam nlsinit(); 287117845Ssam#endif /* NLS_CATALOGS */ 288117845Ssam#endif /* NLS_BUGS */ 289117845Ssam} 290117845Ssam 291117845Ssam#ifndef CLOSE_ON_EXEC 292117845Ssam/* 293117845Ssam * Close files before executing a file. 294117845Ssam * We could be MUCH more intelligent, since (on a version 7 system) 295117845Ssam * we need only close files here during a source, the other 296117845Ssam * shell fd's being in units 16-19 which are closed automatically! 297117845Ssam */ 298117845Ssamvoid 299117845Ssamclosech() 300117845Ssam{ 301117845Ssam register int f; 302117845Ssam 303117845Ssam if (didcch) 304117845Ssam return; 305117845Ssam didcch = 1; 306117845Ssam SHIN = 0; 307117845Ssam SHOUT = 1; 308117845Ssam SHDIAG = 2; 309117845Ssam OLDSTD = 0; 310117845Ssam isoutatty = isatty(SHOUT); 311117845Ssam isdiagatty = isatty(SHDIAG); 312117845Ssam for (f = 3; f < NOFILE; f++) 313117845Ssam (void) close(f); 314117845Ssam} 315117845Ssam 316117845Ssam#endif /* CLOSE_ON_EXEC */ 317117845Ssam 318117845Ssamvoid 319117845Ssamdonefds() 320117845Ssam{ 321117845Ssam 322117845Ssam (void) close(0); 323117845Ssam (void) close(1); 324117845Ssam (void) close(2); 325117845Ssam didfds = 0; 326117845Ssam#ifdef NISPLUS 327117845Ssam { 328117845Ssam int fd = open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 329117845Ssam (void) dup2(fd, 1); 330117845Ssam (void) dup2(fd, 2); 331117845Ssam if (fd != 0) { 332117845Ssam (void) dup2(fd, 0); 333117845Ssam (void) close(fd); 334117845Ssam } 335117845Ssam } 336117845Ssam#endif /*NISPLUS*/ 337117845Ssam} 338117845Ssam 339117845Ssam/* 340117845Ssam * Move descriptor i to j. 341117845Ssam * If j is -1 then we just want to get i to a safe place, 342117845Ssam * i.e. to a unit > 2. This also happens in dcopy. 343117845Ssam */ 344117845Ssamint 345117845Ssamdmove(i, j) 346117845Ssam register int i, j; 347117845Ssam{ 348117845Ssam 349117845Ssam if (i == j || i < 0) 350117845Ssam return (i); 351117845Ssam#ifdef HAVEDUP2 352117845Ssam if (j >= 0) { 353117845Ssam (void) dup2(i, j); 354117845Ssam if (j != i) 355117845Ssam (void) close(i); 356117845Ssam return (j); 357117845Ssam } 358117845Ssam#endif 359117845Ssam j = dcopy(i, j); 360117845Ssam if (j != i) 361117845Ssam (void) close(i); 362117845Ssam return (j); 363117845Ssam} 364117845Ssam 365117845Ssamint 366117845Ssamdcopy(i, j) 367117845Ssam register int i, j; 368117845Ssam{ 369117845Ssam 370117845Ssam if (i == j || i < 0 || (j < 0 && i > 2)) 371117845Ssam return (i); 372117845Ssam if (j >= 0) { 373117845Ssam#ifdef HAVEDUP2 374117845Ssam (void) dup2(i, j); 375117845Ssam return (j); 376117845Ssam#else 377117845Ssam (void) close(j); 378117845Ssam#endif 379117845Ssam } 380117845Ssam return (renum(i, j)); 381117845Ssam} 382117845Ssam 383117845Ssamstatic int 384117845Ssamrenum(i, j) 385117845Ssam register int i, j; 386117845Ssam{ 387117845Ssam register int k = dup(i); 388117845Ssam 389117845Ssam if (k < 0) 390117845Ssam return (-1); 391117845Ssam if (j == -1 && k > 2) 392117845Ssam return (k); 393117845Ssam if (k != j) { 394117845Ssam j = renum(k, j); 395117845Ssam (void) close(k); 396117845Ssam return (j); 397117845Ssam } 398117845Ssam return (k); 399117845Ssam} 400117845Ssam 401117845Ssam/* 402117845Ssam * Left shift a command argument list, discarding 403117845Ssam * the first c arguments. Used in "shift" commands 404117845Ssam * as well as by commands like "repeat". 405117845Ssam */ 406117845Ssamvoid 407117845Ssamlshift(v, c) 408117845Ssam register Char **v; 409117845Ssam register int c; 410117845Ssam{ 411117845Ssam register Char **u; 412117845Ssam 413 for (u = v; *u && --c >= 0; u++) 414 xfree((ptr_t) *u); 415 (void) blkcpy(v, u); 416} 417 418int 419number(cp) 420 Char *cp; 421{ 422 if (!cp) 423 return (0); 424 if (*cp == '-') { 425 cp++; 426 if (!Isdigit(*cp)) 427 return (0); 428 cp++; 429 } 430 while (*cp && Isdigit(*cp)) 431 cp++; 432 return (*cp == 0); 433} 434 435Char ** 436copyblk(v) 437 register Char **v; 438{ 439 register Char **nv = 440 (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 441 442 return (blkcpy(nv, v)); 443} 444 445#ifndef SHORT_STRINGS 446char * 447strend(cp) 448 register char *cp; 449{ 450 if (!cp) 451 return (cp); 452 while (*cp) 453 cp++; 454 return (cp); 455} 456 457#endif /* SHORT_STRINGS */ 458 459Char * 460strip(cp) 461 Char *cp; 462{ 463 register Char *dp = cp; 464 465 if (!cp) 466 return (cp); 467 while ((*dp++ &= TRIM) != '\0') 468 continue; 469 return (cp); 470} 471 472Char * 473quote(cp) 474 Char *cp; 475{ 476 register Char *dp = cp; 477 478 if (!cp) 479 return (cp); 480 while (*dp != '\0') 481 *dp++ |= QUOTE; 482 return (cp); 483} 484 485Char * 486quote_meta(d, s) 487 Char *d; 488 const Char *s; 489{ 490 Char *r = d; 491 while (*s != '\0') { 492 if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB)) 493 *d++ = '\\'; 494 *d++ = *s++; 495 } 496 *d = '\0'; 497 return r; 498} 499 500void 501udvar(name) 502 Char *name; 503{ 504 505 setname(short2str(name)); 506 stderror(ERR_NAME | ERR_UNDVAR); 507} 508 509int 510prefix(sub, str) 511 register Char *sub, *str; 512{ 513 514 for (;;) { 515 if (*sub == 0) 516 return (1); 517 if (*str == 0) 518 return (0); 519 if ((*sub++ & TRIM) != (*str++ & TRIM)) 520 return (0); 521 } 522} 523