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