1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980 Regents of the University of California. 11 * All rights reserved. The Berkeley Software License Agreement 12 * specifies the terms and conditions for redistribution. 13 */ 14 15 #include "sh.h" 16 #include "sh.tconst.h" 17 #include <fcntl.h> 18 #include <unistd.h> 19 20 /* 21 * C Shell 22 */ 23 tchar **blkcat(tchar **, tchar **); 24 tchar **blkend(tchar **); 25 26 int 27 any(int c, tchar *s) 28 { 29 30 while (s && *s) 31 if (*s++ == c) 32 return (1); 33 return (0); 34 } 35 36 int 37 onlyread(tchar *cp) 38 { 39 extern char end[]; 40 41 return ((char *)cp < end); 42 } 43 44 tchar * 45 savestr(tchar *s) 46 { 47 tchar *n; 48 tchar *p; 49 50 if (s == 0) 51 s = S_ /* "" */; 52 #ifndef m32 53 for (p = s; *p++; ) 54 ; 55 n = p = (tchar *)xalloc((unsigned)(p - s)*sizeof (tchar)); 56 while (*p++ = *s++) 57 ; 58 return (n); 59 #else 60 p = (tchar *) xalloc((strlen_(s) + 1)*sizeof (tchar)); 61 strcpy_(p, s); 62 return (p); 63 #endif 64 } 65 66 static void * 67 nomem(size_t i) 68 { 69 #ifdef debug 70 static tchar *av[2] = {0, 0}; 71 #endif 72 73 child++; 74 #ifndef debug 75 error("Out of memory"); 76 #ifdef lint 77 i = i; 78 #endif 79 #else 80 showall(av); 81 printf("i=%d: Out of memory\n", i); 82 chdir("/usr/bill/cshcore"); 83 abort(); 84 #endif 85 return (0); /* fool lint */ 86 } 87 88 tchar ** 89 blkend(tchar **up) 90 { 91 92 while (*up) 93 up++; 94 return (up); 95 } 96 97 void 98 blkpr(tchar **av) 99 { 100 101 for (; *av; av++) { 102 printf("%t", *av); 103 if (av[1]) 104 printf(" "); 105 } 106 } 107 108 int 109 blklen(tchar **av) 110 { 111 int i = 0; 112 113 while (*av++) 114 i++; 115 return (i); 116 } 117 118 tchar ** 119 blkcpy(tchar **oav, tchar **bv) 120 { 121 tchar **av = oav; 122 123 while (*av++ = *bv++) 124 continue; 125 return (oav); 126 } 127 128 tchar ** 129 blkcat(tchar **up, tchar **vp) 130 { 131 132 (void) blkcpy(blkend(up), vp); 133 return (up); 134 } 135 136 void 137 blkfree(tchar **av0) 138 { 139 tchar **av = av0; 140 141 for (; *av; av++) 142 xfree(*av); 143 xfree(av0); 144 } 145 146 tchar ** 147 saveblk(tchar **v) 148 { 149 tchar **newv = 150 (tchar **)xcalloc((unsigned)(blklen(v) + 1), 151 sizeof (tchar **)); 152 tchar **onewv = newv; 153 154 while (*v) 155 *newv++ = savestr(*v++); 156 return (onewv); 157 } 158 159 tchar * 160 strspl(tchar *cp, tchar *dp) 161 { 162 tchar *ep; 163 tchar *p, *q; 164 165 #ifndef m32 166 for (p = cp; *p++; ) 167 ; 168 for (q = dp; *q++; ) 169 ; 170 ep = (tchar *) xalloc((unsigned)(((p - cp) + 171 (q - dp) - 1))*sizeof (tchar)); 172 for (p = ep, q = cp; *p++ = *q++; ) 173 ; 174 for (p--, q = dp; *p++ = *q++; ) 175 ; 176 #else 177 int len1 = strlen_(cp); 178 int len2 = strlen_(dp); 179 180 ep = (tchar *)xalloc((unsigned)(len1 + len2 + 1)*sizeof (tchar)); 181 strcpy_(ep, cp); 182 strcat_(ep, dp); 183 #endif 184 return (ep); 185 } 186 187 tchar ** 188 blkspl(tchar **up, tchar **vp) 189 { 190 tchar **wp = 191 (tchar **)xcalloc((unsigned)(blklen(up) + blklen(vp) + 1), 192 sizeof (tchar **)); 193 194 (void) blkcpy(wp, up); 195 return (blkcat(wp, vp)); 196 } 197 198 int 199 lastchr(tchar *cp) 200 { 201 202 if (!*cp) 203 return (0); 204 while (cp[1]) 205 cp++; 206 return (*cp); 207 } 208 209 void 210 donefds(void) 211 { 212 (void) close(0); 213 (void) close(1); 214 (void) close(2); 215 216 /* 217 * To avoid NIS+ functions to get hold of 0/1/2, 218 * use descriptor 0, and dup it to 1 and 2. 219 */ 220 open("/dev/null", 0); 221 dup(0); dup(0); 222 didfds = 0; 223 } 224 225 /* 226 * Move descriptor i to j. 227 * If j is -1 then we just want to get i to a safe place, 228 * i.e. to a unit > 2. This also happens in dcopy. 229 */ 230 int 231 dmove(int i, int j) 232 { 233 int fd; 234 235 if (i == j || i < 0) 236 return (i); 237 if (j >= 0) { 238 fd = dup2(i, j); 239 if (fd != -1) 240 setfd(fd); 241 } else 242 j = dcopy(i, j); 243 if (j != i) { 244 (void) close(i); 245 unsetfd(i); 246 } 247 return (j); 248 } 249 250 int 251 dcopy(int i, int j) 252 { 253 254 int fd; 255 256 if (i == j || i < 0 || j < 0 && i > 2) 257 return (i); 258 if (j >= 0) { 259 fd = dup2(i, j); 260 if (fd != -1) 261 setfd(fd); 262 return (j); 263 } 264 (void) close(j); 265 unsetfd(j); 266 return (renum(i, j)); 267 } 268 269 int 270 renum(int i, int j) 271 { 272 int k = dup(i); 273 274 if (k < 0) 275 return (-1); 276 if (j == -1 && k > 2) { 277 setfd(k); 278 return (k); 279 } 280 if (k != j) { 281 j = renum(k, j); 282 (void) close(k); /* no need ofr unsetfd() */ 283 return (j); 284 } 285 return (k); 286 } 287 288 #ifndef copy 289 void 290 copy(tchar *to, tchar *from, int size) 291 { 292 293 if (size) 294 do 295 *to++ = *from++; 296 while (--size != 0); 297 } 298 #endif 299 300 /* 301 * Left shift a command argument list, discarding 302 * the first c arguments. Used in "shift" commands 303 * as well as by commands like "repeat". 304 */ 305 void 306 lshift(tchar **v, int c) 307 { 308 tchar **u = v; 309 310 while (*u && --c >= 0) 311 xfree((char *)*u++); 312 (void) blkcpy(v, u); 313 } 314 315 int 316 number(tchar *cp) 317 { 318 319 if (*cp == '-') { 320 cp++; 321 if (!digit(*cp++)) 322 return (0); 323 } 324 while (*cp && digit(*cp)) 325 cp++; 326 return (*cp == 0); 327 } 328 329 tchar ** 330 copyblk(tchar **v) 331 { 332 tchar **nv = 333 (tchar **)xcalloc((unsigned)(blklen(v) + 1), 334 sizeof (tchar **)); 335 336 return (blkcpy(nv, v)); 337 } 338 339 tchar * 340 strend(tchar *cp) 341 { 342 343 while (*cp) 344 cp++; 345 return (cp); 346 } 347 348 tchar * 349 strip(tchar *cp) 350 { 351 tchar *dp = cp; 352 353 while (*dp++ &= TRIM) 354 continue; 355 return (cp); 356 } 357 358 void 359 udvar(tchar *name) 360 { 361 362 setname(name); 363 bferr("Undefined variable"); 364 } 365 366 int 367 prefix(tchar *sub, tchar *str) 368 { 369 370 for (;;) { 371 if (*sub == 0) 372 return (1); 373 if (*str == 0) 374 return (0); 375 if (*sub++ != *str++) 376 return (0); 377 } 378 } 379 380 /* 381 * blk*_ routines 382 */ 383 384 char ** 385 blkend_(char **up) 386 { 387 388 while (*up) 389 up++; 390 return (up); 391 } 392 393 int 394 blklen_(char **av) 395 { 396 int i = 0; 397 398 while (*av++) 399 i++; 400 return (i); 401 } 402 403 char ** 404 blkcpy_(char **oav, char **bv) 405 { 406 char **av = oav; 407 408 while (*av++ = *bv++) 409 continue; 410 return (oav); 411 } 412 413 char ** 414 blkcat_(char **up, char **vp) 415 { 416 417 (void) blkcpy_(blkend_(up), vp); 418 return (up); 419 } 420 421 char ** 422 blkspl_(char **up, char **vp) 423 { 424 char **wp = 425 (char **)xcalloc((unsigned)(blklen_(up) + blklen_(vp) + 1), 426 sizeof (char **)); 427 428 (void) blkcpy_(wp, up); 429 return (blkcat_(wp, vp)); 430 } 431 432 /* 433 * If stack address was passed to free(), we have no good way to see if 434 * they are really in the stack. Therefore, we record the bottom of heap, 435 * and filter out the address not within heap's top(end) and bottom 436 * (xalloc_bottom). 437 */ 438 extern char end[]; 439 static char *xalloc_bottom; 440 441 void * 442 xalloc(size_t size) 443 { 444 char *rptr, *bp; 445 446 if ((rptr = malloc(size)) == NULL) 447 return (nomem(size)); 448 bp = rptr + size; 449 if (bp > xalloc_bottom) 450 xalloc_bottom = bp; 451 return (rptr); 452 } 453 454 void * 455 xrealloc(void *ptr, size_t size) 456 { 457 char *rptr = ptr, *bp; 458 459 if (ptr == NULL) 460 return (xalloc(size)); 461 if (rptr < end) { 462 /* data area, but not in heap area. don't touch it */ 463 oob: 464 if (size == 0) 465 return (NULL); 466 rptr = xalloc(size); 467 /* copy max size */ 468 (void) memcpy(rptr, ptr, size); 469 return (rptr); 470 } 471 if (rptr < xalloc_bottom) { 472 /* address in the heap */ 473 inb: 474 if (size == 0) { 475 free(ptr); 476 return (NULL); 477 } 478 if ((rptr = realloc(ptr, size)) == NULL) 479 return (nomem(size)); 480 bp = rptr + size; 481 if (bp > xalloc_bottom) 482 xalloc_bottom = bp; 483 return (rptr); 484 } 485 #if defined(__sparc) 486 if (rptr > (char *)&rptr) { 487 /* in the stack frame */ 488 goto oob; 489 } 490 #endif 491 /* 492 * can be a memory block returned indirectly from 493 * library functions. update bottom, and check it again. 494 */ 495 xalloc_bottom = sbrk(0); 496 if (rptr <= xalloc_bottom) 497 goto inb; 498 else 499 goto oob; 500 /*NOTREACHED*/ 501 } 502 503 void 504 xfree(void *ptr) 505 { 506 char *rptr = ptr; 507 508 if (rptr < end) { 509 return; 510 } 511 if (rptr < xalloc_bottom) { 512 free(ptr); 513 return; 514 } 515 #if defined(__sparc) 516 if (rptr > (char *)&rptr) { 517 /* in the stack frame */ 518 return; 519 } 520 #endif 521 xalloc_bottom = sbrk(0); 522 if (rptr <= xalloc_bottom) { 523 free(ptr); 524 } 525 } 526 527 void * 528 xcalloc(size_t i, size_t j) 529 { 530 char *cp; 531 532 i *= j; 533 cp = xalloc(i); 534 (void) memset(cp, '\0', i); 535 return (cp); 536 } 537