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