1 /* $Header: /src/pub/tcsh/sh.misc.c,v 3.26 2003/03/12 19:14:51 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.26 2003/03/12 19:14:51 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 NLS_BUGS 262 #ifdef NLS_CATALOGS 263 (void)catclose(catd); 264 #endif /* NLS_CATALOGS */ 265 #endif /* NLS_BUGS */ 266 #ifdef YPBUGS 267 /* suggested by Justin Bur; thanks to Karl Kleinpaste */ 268 fix_yp_bugs(); 269 #endif /* YPBUGS */ 270 for (f = 0; f < NOFILE; f++) 271 if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD && 272 f != FSHTTY 273 #ifdef MALLOC_TRACE 274 && f != 25 275 #endif /* MALLOC_TRACE */ 276 ) 277 { 278 (void) close(f); 279 #ifdef NISPLUS 280 if(f < 3) 281 (void) open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 282 #endif /* NISPLUS */ 283 } 284 #ifdef NLS_BUGS 285 #ifdef NLS_CATALOGS 286 nlsinit(); 287 #endif /* NLS_CATALOGS */ 288 #endif /* NLS_BUGS */ 289 } 290 291 #ifndef CLOSE_ON_EXEC 292 /* 293 * Close files before executing a file. 294 * We could be MUCH more intelligent, since (on a version 7 system) 295 * we need only close files here during a source, the other 296 * shell fd's being in units 16-19 which are closed automatically! 297 */ 298 void 299 closech() 300 { 301 register int f; 302 303 if (didcch) 304 return; 305 didcch = 1; 306 SHIN = 0; 307 SHOUT = 1; 308 SHDIAG = 2; 309 OLDSTD = 0; 310 isoutatty = isatty(SHOUT); 311 isdiagatty = isatty(SHDIAG); 312 for (f = 3; f < NOFILE; f++) 313 (void) close(f); 314 } 315 316 #endif /* CLOSE_ON_EXEC */ 317 318 void 319 donefds() 320 { 321 322 (void) close(0); 323 (void) close(1); 324 (void) close(2); 325 didfds = 0; 326 #ifdef NISPLUS 327 { 328 int fd = open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 329 (void) dup2(fd, 1); 330 (void) dup2(fd, 2); 331 if (fd != 0) { 332 (void) dup2(fd, 0); 333 (void) close(fd); 334 } 335 } 336 #endif /*NISPLUS*/ 337 } 338 339 /* 340 * Move descriptor i to j. 341 * If j is -1 then we just want to get i to a safe place, 342 * i.e. to a unit > 2. This also happens in dcopy. 343 */ 344 int 345 dmove(i, j) 346 register int i, j; 347 { 348 349 if (i == j || i < 0) 350 return (i); 351 #ifdef HAVEDUP2 352 if (j >= 0) { 353 (void) dup2(i, j); 354 if (j != i) 355 (void) close(i); 356 return (j); 357 } 358 #endif 359 j = dcopy(i, j); 360 if (j != i) 361 (void) close(i); 362 return (j); 363 } 364 365 int 366 dcopy(i, j) 367 register int i, j; 368 { 369 370 if (i == j || i < 0 || (j < 0 && i > 2)) 371 return (i); 372 if (j >= 0) { 373 #ifdef HAVEDUP2 374 (void) dup2(i, j); 375 return (j); 376 #else 377 (void) close(j); 378 #endif 379 } 380 return (renum(i, j)); 381 } 382 383 static int 384 renum(i, j) 385 register int i, j; 386 { 387 register int k = dup(i); 388 389 if (k < 0) 390 return (-1); 391 if (j == -1 && k > 2) 392 return (k); 393 if (k != j) { 394 j = renum(k, j); 395 (void) close(k); 396 return (j); 397 } 398 return (k); 399 } 400 401 /* 402 * Left shift a command argument list, discarding 403 * the first c arguments. Used in "shift" commands 404 * as well as by commands like "repeat". 405 */ 406 void 407 lshift(v, c) 408 register Char **v; 409 register int c; 410 { 411 register Char **u; 412 413 for (u = v; *u && --c >= 0; u++) 414 xfree((ptr_t) *u); 415 (void) blkcpy(v, u); 416 } 417 418 int 419 number(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 435 Char ** 436 copyblk(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 446 char * 447 strend(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 459 Char * 460 strip(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 472 Char * 473 quote(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 485 Char * 486 quote_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 500 void 501 udvar(name) 502 Char *name; 503 { 504 505 setname(short2str(name)); 506 stderror(ERR_NAME | ERR_UNDVAR); 507 } 508 509 int 510 prefix(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