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 35 RCSID("$Id: sh.misc.c,v 3.34 2005/01/18 20:24:50 christos Exp $") 36 37 static int renum __P((int, int)); 38 static Char **blkend __P((Char **)); 39 static Char **blkcat __P((Char **, Char **)); 40 41 /* 42 * C Shell 43 */ 44 45 int 46 any(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 58 void 59 setzero(cp, i) 60 char *cp; 61 int i; 62 { 63 if (i != 0) 64 do 65 *cp++ = 0; 66 while (--i); 67 } 68 69 char * 70 strsave(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 86 static Char ** 87 blkend(up) 88 Char **up; 89 { 90 91 while (*up) 92 up++; 93 return (up); 94 } 95 96 97 void 98 blkpr(av) 99 Char **av; 100 { 101 102 for (; *av; av++) { 103 xprintf("%S", *av); 104 if (av[1]) 105 xprintf(" "); 106 } 107 } 108 109 void 110 blkexpand(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 122 int 123 blklen(av) 124 Char **av; 125 { 126 int i = 0; 127 128 while (*av++) 129 i++; 130 return (i); 131 } 132 133 Char ** 134 blkcpy(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 145 static Char ** 146 blkcat(up, vp) 147 Char **up, **vp; 148 { 149 150 (void) blkcpy(blkend(up), vp); 151 return (up); 152 } 153 154 void 155 blkfree(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 167 Char ** 168 saveblk(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 181 char * 182 strstr(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 199 char * 200 strspl(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 220 Char ** 221 blkspl(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 232 Char 233 lastchr(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 */ 250 void 251 closem() 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 */ 292 void 293 closech() 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 312 void 313 donefds() 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 */ 335 int 336 dmove(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 356 int 357 dcopy(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 374 static int 375 renum(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 */ 397 void 398 lshift(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 409 int 410 number(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 426 Char ** 427 copyblk(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 437 char * 438 strend(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 450 Char * 451 strip(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 463 Char * 464 quote(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 476 Char * 477 quote_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 491 void 492 udvar(name) 493 Char *name; 494 { 495 496 setname(short2str(name)); 497 stderror(ERR_NAME | ERR_UNDVAR); 498 } 499 500 int 501 prefix(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