sh.misc.c revision 145479
1/* $Header: /src/pub/tcsh/sh.misc.c,v 3.34 2005/01/18 20:24:50 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. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33#include "sh.h" 34 35RCSID("$Id: sh.misc.c,v 3.34 2005/01/18 20:24:50 christos Exp $") 36 37static int renum __P((int, int)); 38static Char **blkend __P((Char **)); 39static Char **blkcat __P((Char **, Char **)); 40 41/* 42 * C Shell 43 */ 44 45int 46any(s, c) 47 const char *s; 48 Char c; 49{ 50 if (!s) 51 return (0); /* Check for nil pointer */ 52 while (*s) 53 if ((Char)*s++ == c) 54 return (1); 55 return (0); 56} 57 58void 59setzero(cp, i) 60 char *cp; 61 int i; 62{ 63 if (i != 0) 64 do 65 *cp++ = 0; 66 while (--i); 67} 68 69char * 70strsave(s) 71 const char *s; 72{ 73 char *n, *r; 74 const char *p; 75 76 if (s == NULL) 77 s = ""; 78 for (p = s; *p++ != '\0';) 79 continue; 80 r = n = (char *) xmalloc((size_t)((((const char *) p) - s) * sizeof(char))); 81 while ((*n++ = *s++) != '\0') 82 continue; 83 return (r); 84} 85 86static Char ** 87blkend(up) 88 Char **up; 89{ 90 91 while (*up) 92 up++; 93 return (up); 94} 95 96 97void 98blkpr(av) 99 Char **av; 100{ 101 102 for (; *av; av++) { 103 xprintf("%S", *av); 104 if (av[1]) 105 xprintf(" "); 106 } 107} 108 109void 110blkexpand(av, str) 111 Char **av; 112 Char *str; 113{ 114 *str = '\0'; 115 for (; *av; av++) { 116 (void) Strcat(str, *av); 117 if (av[1]) 118 (void) Strcat(str, STRspace); 119 } 120} 121 122int 123blklen(av) 124 Char **av; 125{ 126 int i = 0; 127 128 while (*av++) 129 i++; 130 return (i); 131} 132 133Char ** 134blkcpy(oav, bv) 135 Char **oav; 136 Char **bv; 137{ 138 Char **av = oav; 139 140 while ((*av++ = *bv++) != NULL) 141 continue; 142 return (oav); 143} 144 145static Char ** 146blkcat(up, vp) 147 Char **up, **vp; 148{ 149 150 (void) blkcpy(blkend(up), vp); 151 return (up); 152} 153 154void 155blkfree(av0) 156 Char **av0; 157{ 158 Char **av = av0; 159 160 if (!av0) 161 return; 162 for (; *av; av++) 163 xfree((ptr_t) * av); 164 xfree((ptr_t) av0); 165} 166 167Char ** 168saveblk(v) 169 Char **v; 170{ 171 Char **newv = 172 (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 173 Char **onewv = newv; 174 175 while (*v) 176 *newv++ = Strsave(*v++); 177 return (onewv); 178} 179 180#ifndef HAVE_STRSTR 181char * 182strstr(s, t) 183 const char *s, *t; 184{ 185 do { 186 const char *ss = s; 187 const char *tt = t; 188 189 do 190 if (*tt == '\0') 191 return ((char *) s); 192 while (*ss++ == *tt++); 193 } while (*s++ != '\0'); 194 return (NULL); 195} 196#endif /* !HAVE_STRSTR */ 197 198#ifndef SHORT_STRINGS 199char * 200strspl(cp, dp) 201 const char *cp, *dp; 202{ 203 char *ep; 204 size_t cl, dl; 205 206 if (!cp) 207 cp = ""; 208 if (!dp) 209 dp = ""; 210 cl = strlen(cp); 211 dl = strlen(dp); 212 ep = (char *) xmalloc((cl + dl + 1) * sizeof(char)); 213 memcpy(ep, cp, cl); 214 memcpy(ep + cl, dp, dl + 1); 215 return (ep); 216} 217 218#endif /* !SHORT_STRINGS */ 219 220Char ** 221blkspl(up, vp) 222 Char **up, **vp; 223{ 224 Char **wp = 225 (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1), 226 sizeof(Char **)); 227 228 (void) blkcpy(wp, up); 229 return (blkcat(wp, vp)); 230} 231 232Char 233lastchr(cp) 234 Char *cp; 235{ 236 237 if (!cp) 238 return (0); 239 if (!*cp) 240 return (0); 241 while (cp[1]) 242 cp++; 243 return (*cp); 244} 245 246/* 247 * This routine is called after an error to close up 248 * any units which may have been left open accidentally. 249 */ 250void 251closem() 252{ 253 int f; 254 255#ifdef NLS_BUGS 256#ifdef NLS_CATALOGS 257 nlsclose(); 258#endif /* NLS_CATALOGS */ 259#endif /* NLS_BUGS */ 260#ifdef YPBUGS 261 /* suggested by Justin Bur; thanks to Karl Kleinpaste */ 262 fix_yp_bugs(); 263#endif /* YPBUGS */ 264 for (f = 0; f < NOFILE; f++) 265 if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD && 266 f != FSHTTY 267#ifdef MALLOC_TRACE 268 && f != 25 269#endif /* MALLOC_TRACE */ 270 ) 271 { 272 (void) close(f); 273#ifdef NISPLUS 274 if(f < 3) 275 (void) open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 276#endif /* NISPLUS */ 277 } 278#ifdef NLS_BUGS 279#ifdef NLS_CATALOGS 280 nlsinit(); 281#endif /* NLS_CATALOGS */ 282#endif /* NLS_BUGS */ 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 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|O_LARGEFILE); 323 (void)dcopy(fd, 1); 324 (void)dcopy(fd, 2); 325 (void)dmove(fd, 0); 326 } 327#endif /*NISPLUS*/ 328} 329 330/* 331 * Move descriptor i to j. 332 * If j is -1 then we just want to get i to a safe place, 333 * i.e. to a unit > FSAFE. This also happens in dcopy. 334 */ 335int 336dmove(i, j) 337 int i, j; 338{ 339 340 if (i == j || i < 0) 341 return (i); 342#ifdef HAVE_DUP2 343 if (j >= 0) { 344 (void) dup2(i, j); 345 if (j != i) 346 (void) close(i); 347 return (j); 348 } 349#endif 350 j = dcopy(i, j); 351 if (j != i) 352 (void) close(i); 353 return (j); 354} 355 356int 357dcopy(i, j) 358 int i, j; 359{ 360 361 if (i == j || i < 0 || (j < 0 && i > FSAFE)) 362 return (i); 363 if (j >= 0) { 364#ifdef HAVE_DUP2 365 (void) dup2(i, j); 366 return (j); 367#else 368 (void) close(j); 369#endif 370 } 371 return (renum(i, j)); 372} 373 374static int 375renum(i, j) 376 int i, j; 377{ 378 int k = dup(i); 379 380 if (k < 0) 381 return (-1); 382 if (j == -1 && k > FSAFE) 383 return (k); 384 if (k != j) { 385 j = renum(k, j); 386 (void) close(k); 387 return (j); 388 } 389 return (k); 390} 391 392/* 393 * Left shift a command argument list, discarding 394 * the first c arguments. Used in "shift" commands 395 * as well as by commands like "repeat". 396 */ 397void 398lshift(v, c) 399 Char **v; 400 int c; 401{ 402 Char **u; 403 404 for (u = v; *u && --c >= 0; u++) 405 xfree((ptr_t) *u); 406 (void) blkcpy(v, u); 407} 408 409int 410number(cp) 411 Char *cp; 412{ 413 if (!cp) 414 return (0); 415 if (*cp == '-') { 416 cp++; 417 if (!Isdigit(*cp)) 418 return (0); 419 cp++; 420 } 421 while (*cp && Isdigit(*cp)) 422 cp++; 423 return (*cp == 0); 424} 425 426Char ** 427copyblk(v) 428 Char **v; 429{ 430 Char **nv = 431 (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 432 433 return (blkcpy(nv, v)); 434} 435 436#ifndef SHORT_STRINGS 437char * 438strend(cp) 439 char *cp; 440{ 441 if (!cp) 442 return (cp); 443 while (*cp) 444 cp++; 445 return (cp); 446} 447 448#endif /* SHORT_STRINGS */ 449 450Char * 451strip(cp) 452 Char *cp; 453{ 454 Char *dp = cp; 455 456 if (!cp) 457 return (cp); 458 while ((*dp++ &= TRIM) != '\0') 459 continue; 460 return (cp); 461} 462 463Char * 464quote(cp) 465 Char *cp; 466{ 467 Char *dp = cp; 468 469 if (!cp) 470 return (cp); 471 while (*dp != '\0') 472 *dp++ |= QUOTE; 473 return (cp); 474} 475 476Char * 477quote_meta(d, s) 478 Char *d; 479 const Char *s; 480{ 481 Char *r = d; 482 while (*s != '\0') { 483 if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB)) 484 *d++ = '\\'; 485 *d++ = *s++; 486 } 487 *d = '\0'; 488 return r; 489} 490 491void 492udvar(name) 493 Char *name; 494{ 495 496 setname(short2str(name)); 497 stderror(ERR_NAME | ERR_UNDVAR); 498} 499 500int 501prefix(sub, str) 502 const Char *sub, *str; 503{ 504 505 for (;;) { 506 if (*sub == 0) 507 return (1); 508 if (*str == 0) 509 return (0); 510 if ((*sub++ & TRIM) != (*str++ & TRIM)) 511 return (0); 512 } 513} 514