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 39 RCSID("$Id: sh.misc.c,v 3.23 1997/02/23 19:03:23 christos Exp $") 40 41 static int renum __P((int, int)); 42 static Char **blkend __P((Char **)); 43 static Char **blkcat __P((Char **, Char **)); 44 45 /* 46 * C Shell 47 */ 48 49 int 50 any(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 62 void 63 setzero(cp, i) 64 char *cp; 65 int i; 66 { 67 if (i != 0) 68 do 69 *cp++ = 0; 70 while (--i); 71 } 72 73 char * 74 strsave(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 91 static Char ** 92 blkend(up) 93 register Char **up; 94 { 95 96 while (*up) 97 up++; 98 return (up); 99 } 100 101 102 void 103 blkpr(av) 104 register Char **av; 105 { 106 107 for (; *av; av++) { 108 xprintf("%S", *av); 109 if (av[1]) 110 xprintf(" "); 111 } 112 } 113 114 void 115 blkexpand(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 127 int 128 blklen(av) 129 register Char **av; 130 { 131 register int i = 0; 132 133 while (*av++) 134 i++; 135 return (i); 136 } 137 138 Char ** 139 blkcpy(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 150 static Char ** 151 blkcat(up, vp) 152 Char **up, **vp; 153 { 154 155 (void) blkcpy(blkend(up), vp); 156 return (up); 157 } 158 159 void 160 blkfree(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 172 Char ** 173 saveblk(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) 186 char * 187 strstr(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 205 char * 206 strspl(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 230 Char ** 231 blkspl(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 242 Char 243 lastchr(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 */ 260 void 261 closem() 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 */ 292 void 293 closech() 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 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); 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 */ 338 int 339 dmove(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 359 int 360 dcopy(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 377 static int 378 renum(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 */ 400 void 401 lshift(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 412 int 413 number(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 429 Char ** 430 copyblk(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 440 char * 441 strend(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 453 Char * 454 strip(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 466 Char * 467 quote(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 479 Char * 480 quote_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 494 void 495 udvar(name) 496 Char *name; 497 { 498 499 setname(short2str(name)); 500 stderror(ERR_NAME | ERR_UNDVAR); 501 } 502 503 int 504 prefix(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