sh.misc.c revision 59243
1/* $Header: /src/pub/tcsh/sh.misc.c,v 3.23 1997/02/23 19:03:23 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 "sh.h" 38 39RCSID("$Id: sh.misc.c,v 3.23 1997/02/23 19:03:23 christos Exp $") 40 41static int renum __P((int, int)); 42static Char **blkend __P((Char **)); 43static Char **blkcat __P((Char **, Char **)); 44 45/* 46 * C Shell 47 */ 48 49int 50any(s, c) 51 register char *s; 52 register int c; 53{ 54 if (!s) 55 return (0); /* Check for nil pointer */ 56 while (*s) 57 if (*s++ == c) 58 return (1); 59 return (0); 60} 61 62void 63setzero(cp, i) 64 char *cp; 65 int i; 66{ 67 if (i != 0) 68 do 69 *cp++ = 0; 70 while (--i); 71} 72 73char * 74strsave(s) 75 register const char *s; 76{ 77 char *n; 78 register char *p; 79 80 if (s == NULL) 81 s = (const char *) ""; 82 for (p = (char *) s; *p++ != '\0';) 83 continue; 84 n = p = (char *) xmalloc((size_t) 85 ((((const char *) p) - s) * sizeof(char))); 86 while ((*p++ = *s++) != '\0') 87 continue; 88 return (n); 89} 90 91static Char ** 92blkend(up) 93 register Char **up; 94{ 95 96 while (*up) 97 up++; 98 return (up); 99} 100 101 102void 103blkpr(av) 104 register Char **av; 105{ 106 107 for (; *av; av++) { 108 xprintf("%S", *av); 109 if (av[1]) 110 xprintf(" "); 111 } 112} 113 114void 115blkexpand(av, str) 116 register Char **av; 117 Char *str; 118{ 119 *str = '\0'; 120 for (; *av; av++) { 121 (void) Strcat(str, *av); 122 if (av[1]) 123 (void) Strcat(str, STRspace); 124 } 125} 126 127int 128blklen(av) 129 register Char **av; 130{ 131 register int i = 0; 132 133 while (*av++) 134 i++; 135 return (i); 136} 137 138Char ** 139blkcpy(oav, bv) 140 Char **oav; 141 register Char **bv; 142{ 143 register Char **av = oav; 144 145 while ((*av++ = *bv++) != NULL) 146 continue; 147 return (oav); 148} 149 150static Char ** 151blkcat(up, vp) 152 Char **up, **vp; 153{ 154 155 (void) blkcpy(blkend(up), vp); 156 return (up); 157} 158 159void 160blkfree(av0) 161 Char **av0; 162{ 163 register Char **av = av0; 164 165 if (!av0) 166 return; 167 for (; *av; av++) 168 xfree((ptr_t) * av); 169 xfree((ptr_t) av0); 170} 171 172Char ** 173saveblk(v) 174 register Char **v; 175{ 176 register Char **newv = 177 (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 178 Char **onewv = newv; 179 180 while (*v) 181 *newv++ = Strsave(*v++); 182 return (onewv); 183} 184 185#if !defined(SHORT_STRINGS) && !defined(POSIX) 186char * 187strstr(s, t) 188 register const char *s, *t; 189{ 190 do { 191 register const char *ss = s; 192 register const char *tt = t; 193 194 do 195 if (*tt == '\0') 196 return ((char *) s); 197 while (*ss++ == *tt++); 198 } while (*s++ != '\0'); 199 return (NULL); 200} 201 202#endif /* !SHORT_STRINGS && !POSIX */ 203 204#ifndef SHORT_STRINGS 205char * 206strspl(cp, dp) 207 char *cp, *dp; 208{ 209 char *ep; 210 register char *p, *q; 211 212 if (!cp) 213 cp = ""; 214 if (!dp) 215 dp = ""; 216 for (p = cp; *p++ != '\0';) 217 continue; 218 for (q = dp; *q++ != '\0';) 219 continue; 220 ep = (char *) xmalloc((size_t) (((p - cp) + (q - dp) - 1) * sizeof(char))); 221 for (p = ep, q = cp; (*p++ = *q++) != '\0';) 222 continue; 223 for (p--, q = dp; (*p++ = *q++) != '\0';) 224 continue; 225 return (ep); 226} 227 228#endif /* !SHORT_STRINGS */ 229 230Char ** 231blkspl(up, vp) 232 register Char **up, **vp; 233{ 234 register Char **wp = 235 (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1), 236 sizeof(Char **)); 237 238 (void) blkcpy(wp, up); 239 return (blkcat(wp, vp)); 240} 241 242Char 243lastchr(cp) 244 register Char *cp; 245{ 246 247 if (!cp) 248 return (0); 249 if (!*cp) 250 return (0); 251 while (cp[1]) 252 cp++; 253 return (*cp); 254} 255 256/* 257 * This routine is called after an error to close up 258 * any units which may have been left open accidentally. 259 */ 260void 261closem() 262{ 263 register int f; 264 265#ifdef YPBUGS 266 /* suggested by Justin Bur; thanks to Karl Kleinpaste */ 267 fix_yp_bugs(); 268#endif /* YPBUGS */ 269 for (f = 0; f < NOFILE; f++) 270 if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD && 271 f != FSHTTY 272#ifdef MALLOC_TRACE 273 && f != 25 274#endif /* MALLOC_TRACE */ 275 ) 276 { 277 (void) close(f); 278#ifdef NISPLUS 279 if(f < 3) 280 (void) open(_PATH_DEVNULL, O_RDONLY); 281#endif /* NISPLUS */ 282 } 283} 284 285#ifndef CLOSE_ON_EXEC 286/* 287 * Close files before executing a file. 288 * We could be MUCH more intelligent, since (on a version 7 system) 289 * we need only close files here during a source, the other 290 * shell fd's being in units 16-19 which are closed automatically! 291 */ 292void 293closech() 294{ 295 register int f; 296 297 if (didcch) 298 return; 299 didcch = 1; 300 SHIN = 0; 301 SHOUT = 1; 302 SHDIAG = 2; 303 OLDSTD = 0; 304 isoutatty = isatty(SHOUT); 305 isdiagatty = isatty(SHDIAG); 306 for (f = 3; f < NOFILE; f++) 307 (void) close(f); 308} 309 310#endif /* CLOSE_ON_EXEC */ 311 312void 313donefds() 314{ 315 316 (void) close(0); 317 (void) close(1); 318 (void) close(2); 319 didfds = 0; 320#ifdef NISPLUS 321 { 322 int fd = open(_PATH_DEVNULL, O_RDONLY); 323 (void) dup2(fd, 1); 324 (void) dup2(fd, 2); 325 if (fd != 0) { 326 (void) dup2(fd, 0); 327 (void) close(fd); 328 } 329 } 330#endif /*NISPLUS*/ 331} 332 333/* 334 * Move descriptor i to j. 335 * If j is -1 then we just want to get i to a safe place, 336 * i.e. to a unit > 2. This also happens in dcopy. 337 */ 338int 339dmove(i, j) 340 register int i, j; 341{ 342 343 if (i == j || i < 0) 344 return (i); 345#ifdef HAVEDUP2 346 if (j >= 0) { 347 (void) dup2(i, j); 348 if (j != i) 349 (void) close(i); 350 return (j); 351 } 352#endif 353 j = dcopy(i, j); 354 if (j != i) 355 (void) close(i); 356 return (j); 357} 358 359int 360dcopy(i, j) 361 register int i, j; 362{ 363 364 if (i == j || i < 0 || (j < 0 && i > 2)) 365 return (i); 366 if (j >= 0) { 367#ifdef HAVEDUP2 368 (void) dup2(i, j); 369 return (j); 370#else 371 (void) close(j); 372#endif 373 } 374 return (renum(i, j)); 375} 376 377static int 378renum(i, j) 379 register int i, j; 380{ 381 register int k = dup(i); 382 383 if (k < 0) 384 return (-1); 385 if (j == -1 && k > 2) 386 return (k); 387 if (k != j) { 388 j = renum(k, j); 389 (void) close(k); 390 return (j); 391 } 392 return (k); 393} 394 395/* 396 * Left shift a command argument list, discarding 397 * the first c arguments. Used in "shift" commands 398 * as well as by commands like "repeat". 399 */ 400void 401lshift(v, c) 402 register Char **v; 403 register int c; 404{ 405 register Char **u; 406 407 for (u = v; *u && --c >= 0; u++) 408 xfree((ptr_t) *u); 409 (void) blkcpy(v, u); 410} 411 412int 413number(cp) 414 Char *cp; 415{ 416 if (!cp) 417 return (0); 418 if (*cp == '-') { 419 cp++; 420 if (!Isdigit(*cp)) 421 return (0); 422 cp++; 423 } 424 while (*cp && Isdigit(*cp)) 425 cp++; 426 return (*cp == 0); 427} 428 429Char ** 430copyblk(v) 431 register Char **v; 432{ 433 register Char **nv = 434 (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 435 436 return (blkcpy(nv, v)); 437} 438 439#ifndef SHORT_STRINGS 440char * 441strend(cp) 442 register char *cp; 443{ 444 if (!cp) 445 return (cp); 446 while (*cp) 447 cp++; 448 return (cp); 449} 450 451#endif /* SHORT_STRINGS */ 452 453Char * 454strip(cp) 455 Char *cp; 456{ 457 register Char *dp = cp; 458 459 if (!cp) 460 return (cp); 461 while ((*dp++ &= TRIM) != '\0') 462 continue; 463 return (cp); 464} 465 466Char * 467quote(cp) 468 Char *cp; 469{ 470 register Char *dp = cp; 471 472 if (!cp) 473 return (cp); 474 while (*dp != '\0') 475 *dp++ |= QUOTE; 476 return (cp); 477} 478 479Char * 480quote_meta(d, s) 481 Char *d; 482 const Char *s; 483{ 484 Char *r = d; 485 while (*s != '\0') { 486 if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB)) 487 *d++ = '\\'; 488 *d++ = *s++; 489 } 490 *d = '\0'; 491 return r; 492} 493 494void 495udvar(name) 496 Char *name; 497{ 498 499 setname(short2str(name)); 500 stderror(ERR_NAME | ERR_UNDVAR); 501} 502 503int 504prefix(sub, str) 505 register Char *sub, *str; 506{ 507 508 for (;;) { 509 if (*sub == 0) 510 return (1); 511 if (*str == 0) 512 return (0); 513 if ((*sub++ & TRIM) != (*str++ & TRIM)) 514 return (0); 515 } 516} 517