1 0 stevel /* 2 2182 chin * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 0 stevel * Use is subject to license terms. 4 0 stevel */ 5 0 stevel 6 0 stevel /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 0 stevel /* All Rights Reserved */ 8 0 stevel 9 0 stevel /* 10 0 stevel * Copyright (c) 1980 Regents of the University of California. 11 0 stevel * All rights reserved. The Berkeley Software License Agreement 12 0 stevel * specifies the terms and conditions for redistribution. 13 0 stevel */ 14 0 stevel 15 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 16 0 stevel 17 0 stevel #include "sh.h" 18 0 stevel #include <locale.h> /* For LC_ALL */ 19 0 stevel #include "sh.tconst.h" 20 0 stevel #include <sys/types.h> 21 0 stevel #include <stdlib.h> 22 0 stevel 23 0 stevel /* 24 0 stevel * N.B.: Some of the limits change from SunOS 4.x to SunOS 5.0. In 25 0 stevel * particular, RLIMIT_RSS is gone and RLIMIT_VMEM is new. Beware of consusing 26 0 stevel * the keywords that the command prints for these two. The old one was 27 0 stevel * "memoryuse" and the new one is "memorysize". Note also that a given limit 28 0 stevel * doesn't necessarily appear in the same position in the two releases. 29 0 stevel */ 30 0 stevel struct limits { 31 0 stevel int limconst; 32 0 stevel tchar *limname; 33 0 stevel int limdiv; 34 0 stevel tchar *limscale; 35 0 stevel } limits[] = { 36 0 stevel RLIMIT_CPU, S_cputime, /* "cputime" */ 37 0 stevel 1, S_seconds, /* "seconds" */ 38 0 stevel RLIMIT_FSIZE, S_filesize, /* "filesize" */ 39 0 stevel 1024, S_kbytes, /* "kbytes" */ 40 0 stevel RLIMIT_DATA, S_datasize, /* "datasize" */ 41 0 stevel 1024, S_kbytes, /* "kbytes" */ 42 0 stevel RLIMIT_STACK, S_stacksize, /* "stacksize" */ 43 0 stevel 1024, S_kbytes, /* "kbytes" */ 44 0 stevel RLIMIT_CORE, S_coredumpsize, /* "coredumpsize" */ 45 0 stevel 1024, S_kbytes, /* "kbytes" */ 46 0 stevel RLIMIT_NOFILE, S_descriptors, /* "descriptors" */ 47 0 stevel 1, S_, /* "" */ 48 0 stevel RLIMIT_VMEM, S_memorysize, /* "memorysize" */ 49 0 stevel 1024, S_kbytes, /* "kbytes" */ 50 0 stevel -1, 0, 51 0 stevel }; 52 0 stevel 53 356 muffin 54 0 stevel static int getval(struct limits *lp, tchar **v, rlim_t *); 55 356 muffin void islogin(void); 56 356 muffin int dolabel(void); 57 0 stevel void reexecute(struct command *kp); 58 356 muffin void preread_(void); 59 356 muffin void doagain(void); 60 356 muffin void toend(void); 61 356 muffin void wfree(void); 62 0 stevel void echo(tchar sep, tchar **v); 63 0 stevel void local_setenv(tchar *name, tchar *val); 64 0 stevel void local_unsetenv(tchar *name); 65 0 stevel void limtail(tchar *cp, tchar *str0); 66 0 stevel void plim(struct limits *lp, tchar hard); 67 0 stevel void search(); 68 0 stevel 69 0 stevel #define BUFSZ 1028 70 0 stevel 71 0 stevel /* 72 0 stevel * C shell 73 0 stevel */ 74 0 stevel 75 356 muffin struct biltins * 76 0 stevel isbfunc(struct command *t) 77 0 stevel { 78 0 stevel tchar *cp = t->t_dcom[0]; 79 0 stevel struct biltins *bp, *bp1, *bp2; 80 0 stevel int dofg1(), dobg1(); 81 0 stevel 82 0 stevel static struct biltins label = { S_, dolabel, 0, 0 }; 83 0 stevel static struct biltins foregnd = { S_Pjob, dofg1, 0, 0 }; 84 0 stevel static struct biltins backgnd = { S_PjobAND, dobg1, 0, 0 }; 85 0 stevel #ifdef TRACE 86 0 stevel tprintf("TRACE- isbfunc()\n"); 87 0 stevel #endif 88 0 stevel if (lastchr(cp) == ':') { 89 0 stevel label.bname = cp; 90 0 stevel return (&label); 91 0 stevel } 92 0 stevel if (*cp == '%') { 93 0 stevel if (t->t_dflg & FAND) { 94 0 stevel t->t_dflg &= ~FAND; 95 0 stevel backgnd.bname = cp; 96 0 stevel return (&backgnd); 97 0 stevel } 98 0 stevel foregnd.bname = cp; 99 0 stevel return (&foregnd); 100 0 stevel } 101 0 stevel /* 102 0 stevel * Binary search 103 0 stevel * Bp1 is the beginning of the current search range. 104 0 stevel * Bp2 is one past the end. 105 0 stevel */ 106 0 stevel for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2; ) { 107 0 stevel int i; 108 0 stevel 109 0 stevel bp = bp1 + (bp2 - bp1 >> 1); 110 0 stevel if ((i = *cp - *bp->bname) == 0 && 111 0 stevel (i = strcmp_(cp, bp->bname)) == 0) { 112 0 stevel return (bp); 113 0 stevel } 114 0 stevel if (i < 0) { 115 0 stevel bp2 = bp; 116 0 stevel } else { 117 0 stevel bp1 = bp + 1; 118 0 stevel } 119 0 stevel } 120 0 stevel return (0); 121 0 stevel } 122 0 stevel 123 0 stevel void 124 0 stevel func(struct command *t, struct biltins *bp) 125 0 stevel { 126 0 stevel int i; 127 0 stevel 128 0 stevel #ifdef TRACE 129 0 stevel tprintf("TRACE- func()\n"); 130 0 stevel #endif 131 0 stevel xechoit(t->t_dcom); 132 0 stevel setname(bp->bname); 133 0 stevel i = blklen(t->t_dcom) - 1; 134 0 stevel if (i < bp->minargs) { 135 0 stevel bferr("Too few arguments"); 136 0 stevel } 137 0 stevel if (i > bp->maxargs) { 138 0 stevel bferr("Too many arguments"); 139 0 stevel } 140 0 stevel (*bp->bfunct)(t->t_dcom, t); 141 0 stevel } 142 0 stevel 143 0 stevel int 144 356 muffin dolabel(void) 145 0 stevel { 146 0 stevel #ifdef TRACE 147 0 stevel tprintf("TRACE- dolabel()\n"); 148 0 stevel #endif 149 356 muffin return (0); 150 0 stevel } 151 0 stevel 152 0 stevel void 153 0 stevel doonintr(tchar **v) 154 0 stevel { 155 0 stevel tchar *cp; 156 0 stevel tchar *vv = v[1]; 157 0 stevel 158 0 stevel #ifdef TRACE 159 0 stevel tprintf("TRACE- doonintr()\n"); 160 0 stevel #endif 161 0 stevel if (parintr == SIG_IGN) { 162 0 stevel return; 163 0 stevel } 164 0 stevel if (setintr && intty) { 165 0 stevel bferr("Can't from terminal"); 166 0 stevel } 167 0 stevel cp = gointr, gointr = 0, xfree(cp); 168 0 stevel if (vv == 0) { 169 0 stevel if (setintr) { 170 0 stevel (void) sigblock(sigmask(SIGINT)); 171 0 stevel } else { 172 0 stevel (void) signal(SIGINT, SIG_DFL); 173 0 stevel } 174 0 stevel gointr = 0; 175 0 stevel } else if (eq((vv = strip(vv)), S_MINUS)) { 176 0 stevel (void) signal(SIGINT, SIG_IGN); 177 0 stevel gointr = S_MINUS; 178 0 stevel } else { 179 0 stevel gointr = savestr(vv); 180 0 stevel (void) signal(SIGINT, pintr); 181 0 stevel } 182 0 stevel } 183 0 stevel 184 0 stevel void 185 356 muffin donohup(void) 186 0 stevel { 187 0 stevel 188 0 stevel #ifdef TRACE 189 0 stevel tprintf("TRACE- donohup()\n"); 190 0 stevel #endif 191 0 stevel if (intty) { 192 0 stevel bferr("Can't from terminal"); 193 0 stevel } 194 0 stevel if (setintr == 0) { 195 0 stevel (void) signal(SIGHUP, SIG_IGN); 196 0 stevel #ifdef CC 197 0 stevel submit(getpid()); 198 0 stevel #endif 199 0 stevel } 200 0 stevel } 201 0 stevel 202 0 stevel void 203 356 muffin dozip(void) 204 0 stevel { 205 0 stevel ; 206 0 stevel } 207 0 stevel 208 0 stevel void 209 356 muffin prvars(void) 210 0 stevel { 211 0 stevel #ifdef TRACE 212 0 stevel tprintf("TRACE- prvars()\n"); 213 0 stevel #endif 214 0 stevel 215 0 stevel plist(&shvhed); 216 0 stevel } 217 0 stevel 218 0 stevel void 219 0 stevel doalias(tchar **v) 220 0 stevel { 221 0 stevel struct varent *vp; 222 0 stevel tchar *p; 223 0 stevel 224 0 stevel #ifdef TRACE 225 0 stevel tprintf("TRACE- doalias()\n"); 226 0 stevel #endif 227 0 stevel v++; 228 0 stevel p = *v++; 229 0 stevel if (p == 0) { 230 0 stevel plist(&aliases); 231 0 stevel } else if (*v == 0) { 232 0 stevel vp = adrof1(strip(p), &aliases); 233 0 stevel if (vp) { 234 0 stevel blkpr(vp->vec), printf("\n"); 235 0 stevel } 236 0 stevel } else { 237 0 stevel if (eq(p, S_alias) || 238 0 stevel eq(p, S_unalias)) { 239 0 stevel setname(p); 240 0 stevel bferr("Too dangerous to alias that"); 241 0 stevel } 242 0 stevel set1(strip(p), saveblk(v), &aliases); 243 0 stevel } 244 0 stevel } 245 0 stevel 246 0 stevel void 247 0 stevel unalias(tchar **v) 248 0 stevel { 249 0 stevel 250 0 stevel #ifdef TRACE 251 0 stevel tprintf("TRACE- unalias()\n"); 252 0 stevel #endif 253 0 stevel unset1(v, &aliases); 254 0 stevel } 255 0 stevel 256 0 stevel void 257 356 muffin dologout(void) 258 0 stevel { 259 0 stevel 260 0 stevel #ifdef TRACE 261 0 stevel tprintf("TRACE- dologout()\n"); 262 0 stevel #endif 263 0 stevel islogin(); 264 0 stevel goodbye(); 265 0 stevel } 266 0 stevel 267 0 stevel void 268 0 stevel dologin(tchar **v) 269 0 stevel { 270 0 stevel 271 0 stevel char *v_; /* work */ 272 0 stevel #ifdef TRACE 273 0 stevel tprintf("TRACE- dologin()\n"); 274 0 stevel #endif 275 0 stevel islogin(); 276 0 stevel rechist(); 277 0 stevel (void) signal(SIGTERM, parterm); 278 0 stevel if (v[1] != NULL) { 279 0 stevel v_ = tstostr(NULL, v[1]); /* No need to free */ 280 0 stevel } else { 281 0 stevel v_ = 0; 282 0 stevel } 283 0 stevel execl("/bin/login", "login", v_, 0); 284 0 stevel untty(); 285 0 stevel exit(1); 286 0 stevel } 287 0 stevel 288 0 stevel #ifdef NEWGRP 289 0 stevel void 290 0 stevel donewgrp(tchar **v) 291 0 stevel { 292 0 stevel 293 0 stevel char *v_; /* work */ 294 0 stevel #ifdef TRACE 295 0 stevel tprintf("TRACE- donewgrp()\n"); 296 0 stevel #endif 297 0 stevel if (chkstop == 0 && setintr) { 298 0 stevel panystop(0); 299 0 stevel } 300 0 stevel (void) signal(SIGTERM, parterm); 301 0 stevel 302 0 stevel if (v[1] != NULL) { 303 0 stevel v_ = tstostr(NOSTR, v[1]); /* No need to free */ 304 0 stevel } else { 305 0 stevel v_ = 0; 306 0 stevel } 307 0 stevel execl("/bin/newgrp", "newgrp", v_, 0); 308 0 stevel execl("/usr/bin/newgrp", "newgrp", v_, 0); 309 0 stevel untty(); 310 0 stevel exit(1); 311 0 stevel } 312 0 stevel #endif 313 0 stevel 314 0 stevel void 315 356 muffin islogin(void) 316 0 stevel { 317 0 stevel 318 0 stevel #ifdef TRACE 319 0 stevel tprintf("TRACE- islogin()\n"); 320 0 stevel #endif 321 0 stevel if (chkstop == 0 && setintr) { 322 0 stevel panystop(0); 323 0 stevel } 324 0 stevel if (loginsh) { 325 0 stevel return; 326 0 stevel } 327 0 stevel error("Not login shell"); 328 0 stevel } 329 0 stevel 330 0 stevel void 331 0 stevel doif(tchar **v, struct command *kp) 332 0 stevel { 333 0 stevel int i; 334 0 stevel tchar **vv; 335 0 stevel 336 0 stevel #ifdef TRACE 337 0 stevel tprintf("TRACE- doif()\n"); 338 0 stevel #endif 339 0 stevel v++; 340 0 stevel i = exp(&v); 341 0 stevel vv = v; 342 0 stevel if (*vv == NOSTR) { 343 0 stevel bferr("Empty if"); 344 0 stevel } 345 0 stevel if (eq(*vv, S_then)) { 346 0 stevel if (*++vv) { 347 0 stevel bferr("Improper then"); 348 0 stevel } 349 0 stevel setname(S_then); 350 0 stevel /* 351 0 stevel * If expression was zero, then scan to else, 352 0 stevel * otherwise just fall into following code. 353 0 stevel */ 354 0 stevel if (!i) { 355 0 stevel search(ZIF, 0); 356 0 stevel } 357 0 stevel return; 358 0 stevel } 359 0 stevel /* 360 0 stevel * Simple command attached to this if. 361 0 stevel * Left shift the node in this tree, munging it 362 0 stevel * so we can reexecute it. 363 0 stevel */ 364 0 stevel if (i) { 365 0 stevel lshift(kp->t_dcom, vv - kp->t_dcom); 366 0 stevel reexecute(kp); 367 0 stevel donefds(); 368 0 stevel } 369 0 stevel } 370 0 stevel 371 0 stevel /* 372 0 stevel * Reexecute a command, being careful not 373 0 stevel * to redo i/o redirection, which is already set up. 374 0 stevel */ 375 0 stevel void 376 0 stevel reexecute(struct command *kp) 377 0 stevel { 378 0 stevel 379 0 stevel #ifdef TRACE 380 0 stevel tprintf("TRACE- reexecute()\n"); 381 0 stevel #endif 382 0 stevel kp->t_dflg &= FSAVE; 383 0 stevel kp->t_dflg |= FREDO; 384 0 stevel /* 385 0 stevel * If tty is still ours to arbitrate, arbitrate it; 386 0 stevel * otherwise dont even set pgrp's as the jobs would 387 0 stevel * then have no way to get the tty (we can't give it 388 0 stevel * to them, and our parent wouldn't know their pgrp, etc. 389 0 stevel */ 390 0 stevel execute(kp, tpgrp > 0 ? tpgrp : -1); 391 0 stevel } 392 0 stevel 393 0 stevel void 394 356 muffin doelse(void) 395 0 stevel { 396 0 stevel 397 0 stevel #ifdef TRACE 398 0 stevel tprintf("TRACE- doelse()\n"); 399 0 stevel #endif 400 0 stevel search(ZELSE, 0); 401 0 stevel } 402 0 stevel 403 0 stevel void 404 0 stevel dogoto(tchar **v) 405 0 stevel { 406 0 stevel struct whyle *wp; 407 0 stevel tchar *lp; 408 0 stevel #ifdef TRACE 409 0 stevel tprintf("TRACE- dogoto()\n"); 410 0 stevel #endif 411 0 stevel 412 0 stevel /* 413 0 stevel * While we still can, locate any unknown ends of existing loops. 414 0 stevel * This obscure code is the WORST result of the fact that we 415 0 stevel * don't really parse. 416 0 stevel */ 417 0 stevel for (wp = whyles; wp; wp = wp->w_next) { 418 0 stevel if (wp->w_end == 0) { 419 0 stevel search(ZBREAK, 0); 420 0 stevel wp->w_end = btell(); 421 0 stevel } else { 422 0 stevel bseek(wp->w_end); 423 0 stevel } 424 0 stevel } 425 0 stevel search(ZGOTO, 0, lp = globone(v[1])); 426 0 stevel xfree(lp); 427 0 stevel /* 428 0 stevel * Eliminate loops which were exited. 429 0 stevel */ 430 0 stevel wfree(); 431 0 stevel } 432 0 stevel 433 0 stevel void 434 0 stevel doswitch(tchar **v) 435 0 stevel { 436 0 stevel tchar *cp, *lp; 437 0 stevel 438 0 stevel #ifdef TRACE 439 0 stevel tprintf("TRACE- doswitch()\n"); 440 0 stevel #endif 441 0 stevel v++; 442 0 stevel if (!*v || *(*v++) != '(') { 443 0 stevel goto syntax; 444 0 stevel } 445 0 stevel cp = **v == ')' ? S_ : *v++; 446 0 stevel if (*(*v++) != ')') { 447 0 stevel v--; 448 0 stevel } 449 0 stevel if (*v) { 450 0 stevel syntax: 451 0 stevel error("Syntax error"); 452 0 stevel } 453 0 stevel search(ZSWITCH, 0, lp = globone(cp)); 454 0 stevel xfree(lp); 455 0 stevel } 456 0 stevel 457 0 stevel void 458 356 muffin dobreak(void) 459 0 stevel { 460 0 stevel 461 0 stevel #ifdef TRACE 462 0 stevel tprintf("TRACE- dobreak()\n"); 463 0 stevel #endif 464 0 stevel if (whyles) { 465 0 stevel toend(); 466 0 stevel } else { 467 0 stevel bferr("Not in while/foreach"); 468 0 stevel } 469 0 stevel } 470 0 stevel 471 0 stevel void 472 0 stevel doexit(tchar **v) 473 0 stevel { 474 0 stevel 475 0 stevel #ifdef TRACE 476 0 stevel tprintf("TRACE- doexit()\n"); 477 0 stevel #endif 478 0 stevel if (chkstop == 0) { 479 0 stevel panystop(0); 480 0 stevel } 481 0 stevel /* 482 0 stevel * Don't DEMAND parentheses here either. 483 0 stevel */ 484 0 stevel v++; 485 0 stevel if (*v) { 486 0 stevel set(S_status, putn(exp(&v))); 487 0 stevel if (*v) { 488 0 stevel bferr("Expression syntax"); 489 0 stevel } 490 0 stevel } 491 0 stevel btoeof(); 492 0 stevel if (intty) { 493 0 stevel (void) close(SHIN); 494 0 stevel unsetfd(SHIN); 495 0 stevel } 496 0 stevel } 497 0 stevel 498 0 stevel void 499 0 stevel doforeach(tchar **v) 500 0 stevel { 501 0 stevel tchar *cp; 502 0 stevel struct whyle *nwp; 503 0 stevel 504 0 stevel #ifdef TRACE 505 0 stevel tprintf("TRACE- doforeach()\n"); 506 0 stevel #endif 507 0 stevel v++; 508 0 stevel cp = strip(*v); 509 0 stevel while (*cp && alnum(*cp)) { 510 0 stevel cp++; 511 0 stevel } 512 2182 chin if (*cp || strlen_(*v) >= MAX_VAR_LEN || !letter(**v)) { 513 0 stevel bferr("Invalid variable"); 514 0 stevel } 515 0 stevel cp = *v++; 516 0 stevel if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') { 517 0 stevel bferr("Words not ()'ed"); 518 0 stevel } 519 0 stevel v++; 520 0 stevel gflag = 0, tglob(v); 521 0 stevel v = glob(v); 522 0 stevel if (v == 0) { 523 0 stevel bferr("No match"); 524 0 stevel } 525 559 nakanon nwp = (struct whyle *)xcalloc(1, sizeof (*nwp)); 526 0 stevel nwp->w_fe = nwp->w_fe0 = v; gargv = 0; 527 0 stevel nwp->w_start = btell(); 528 0 stevel nwp->w_fename = savestr(cp); 529 0 stevel nwp->w_next = whyles; 530 0 stevel whyles = nwp; 531 0 stevel /* 532 0 stevel * Pre-read the loop so as to be more 533 0 stevel * comprehensible to a terminal user. 534 0 stevel */ 535 0 stevel if (intty) { 536 0 stevel preread_(); 537 0 stevel } 538 0 stevel doagain(); 539 0 stevel } 540 0 stevel 541 0 stevel void 542 0 stevel dowhile(tchar **v) 543 0 stevel { 544 0 stevel int status; 545 0 stevel bool again = whyles != 0 && whyles->w_start == lineloc && 546 0 stevel whyles->w_fename == 0; 547 0 stevel 548 0 stevel #ifdef TRACE 549 0 stevel tprintf("TRACE- dowhile()\n"); 550 0 stevel #endif 551 0 stevel v++; 552 0 stevel /* 553 0 stevel * Implement prereading here also, taking care not to 554 0 stevel * evaluate the expression before the loop has been read up 555 0 stevel * from a terminal. 556 0 stevel */ 557 0 stevel if (intty && !again) { 558 0 stevel status = !exp0(&v, 1); 559 0 stevel } else { 560 0 stevel status = !exp(&v); 561 0 stevel } 562 0 stevel if (*v) { 563 0 stevel bferr("Expression syntax"); 564 0 stevel } 565 0 stevel if (!again) { 566 559 nakanon struct whyle *nwp = (struct whyle *)xcalloc(1, sizeof (*nwp)); 567 0 stevel 568 0 stevel nwp->w_start = lineloc; 569 0 stevel nwp->w_end = 0; 570 0 stevel nwp->w_next = whyles; 571 0 stevel whyles = nwp; 572 0 stevel if (intty) { 573 0 stevel /* 574 0 stevel * The tty preread 575 0 stevel */ 576 0 stevel preread_(); 577 0 stevel doagain(); 578 0 stevel return; 579 0 stevel } 580 0 stevel } 581 0 stevel if (status) { 582 0 stevel /* We ain't gonna loop no more, no more! */ 583 0 stevel toend(); 584 0 stevel } 585 0 stevel } 586 0 stevel 587 0 stevel void 588 356 muffin preread_(void) 589 0 stevel { 590 0 stevel #ifdef TRACE 591 0 stevel tprintf("TRACE- preread()\n"); 592 0 stevel #endif 593 0 stevel 594 0 stevel whyles->w_end = -1; 595 0 stevel if (setintr) { 596 0 stevel (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); 597 0 stevel } 598 0 stevel search(ZBREAK, 0); 599 0 stevel if (setintr) { 600 0 stevel (void) sigblock(sigmask(SIGINT)); 601 0 stevel } 602 0 stevel whyles->w_end = btell(); 603 0 stevel } 604 0 stevel 605 0 stevel void 606 356 muffin doend(void) 607 0 stevel { 608 0 stevel 609 0 stevel #ifdef TRACE 610 0 stevel tprintf("TRACE- doend()\n"); 611 0 stevel #endif 612 0 stevel if (!whyles) { 613 0 stevel bferr("Not in while/foreach"); 614 0 stevel } 615 0 stevel whyles->w_end = btell(); 616 0 stevel doagain(); 617 0 stevel } 618 0 stevel 619 0 stevel void 620 356 muffin docontin(void) 621 0 stevel { 622 0 stevel #ifdef TRACE 623 0 stevel tprintf("TRACE- docontin()\n"); 624 0 stevel #endif 625 0 stevel 626 0 stevel if (!whyles) { 627 0 stevel bferr("Not in while/foreach"); 628 0 stevel } 629 0 stevel doagain(); 630 0 stevel } 631 0 stevel 632 0 stevel void 633 356 muffin doagain(void) 634 0 stevel { 635 0 stevel 636 0 stevel #ifdef TRACE 637 0 stevel tprintf("TRACE- doagain()\n"); 638 0 stevel #endif 639 0 stevel /* Repeating a while is simple */ 640 0 stevel if (whyles->w_fename == 0) { 641 0 stevel bseek(whyles->w_start); 642 0 stevel return; 643 0 stevel } 644 0 stevel /* 645 0 stevel * The foreach variable list actually has a spurious word 646 0 stevel * ")" at the end of the w_fe list. Thus we are at the 647 0 stevel * of the list if one word beyond this is 0. 648 0 stevel */ 649 0 stevel if (!whyles->w_fe[1]) { 650 0 stevel dobreak(); 651 0 stevel return; 652 0 stevel } 653 0 stevel set(whyles->w_fename, savestr(*whyles->w_fe++)); 654 0 stevel bseek(whyles->w_start); 655 0 stevel } 656 0 stevel 657 0 stevel void 658 0 stevel dorepeat(tchar **v, struct command *kp) 659 0 stevel { 660 0 stevel int i, omask; 661 0 stevel 662 0 stevel #ifdef TRACE 663 0 stevel tprintf("TRACE- dorepeat()\n"); 664 0 stevel #endif 665 0 stevel i = getn(v[1]); 666 0 stevel if (setintr) { 667 0 stevel omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 668 0 stevel } 669 0 stevel lshift(v, 2); 670 0 stevel while (i > 0) { 671 0 stevel if (setintr) { 672 0 stevel (void) sigsetmask(omask); 673 0 stevel } 674 0 stevel reexecute(kp); 675 0 stevel --i; 676 0 stevel } 677 0 stevel donefds(); 678 0 stevel if (setintr) { 679 0 stevel (void) sigsetmask(omask); 680 0 stevel } 681 0 stevel } 682 0 stevel 683 0 stevel void 684 356 muffin doswbrk(void) 685 0 stevel { 686 0 stevel 687 0 stevel #ifdef TRACE 688 0 stevel tprintf("TRACE- doswbrk()\n"); 689 0 stevel #endif 690 0 stevel search(ZBRKSW, 0); 691 0 stevel } 692 0 stevel 693 0 stevel int 694 0 stevel srchx(tchar *cp) 695 0 stevel { 696 0 stevel struct srch *sp, *sp1, *sp2; 697 0 stevel int i; 698 0 stevel 699 0 stevel #ifdef TRACE 700 0 stevel tprintf("TRACE- srchx()\n"); 701 0 stevel #endif 702 0 stevel /* 703 0 stevel * Binary search 704 0 stevel * Sp1 is the beginning of the current search range. 705 0 stevel * Sp2 is one past the end. 706 0 stevel */ 707 0 stevel for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2; ) { 708 0 stevel sp = sp1 + (sp2 - sp1 >> 1); 709 0 stevel if ((i = *cp - *sp->s_name) == 0 && 710 0 stevel (i = strcmp_(cp, sp->s_name)) == 0) { 711 0 stevel return (sp->s_value); 712 0 stevel } 713 0 stevel if (i < 0) { 714 0 stevel sp2 = sp; 715 0 stevel } else { 716 0 stevel sp1 = sp + 1; 717 0 stevel } 718 0 stevel } 719 0 stevel return (-1); 720 0 stevel } 721 0 stevel 722 0 stevel tchar Stype; 723 0 stevel tchar *Sgoal; 724 0 stevel 725 0 stevel /*VARARGS2*/ 726 0 stevel void 727 0 stevel search(type, level, goal) 728 0 stevel int type; int level; tchar *goal; 729 0 stevel { 730 0 stevel tchar wordbuf[BUFSIZ]; 731 0 stevel tchar *aword = wordbuf; 732 0 stevel tchar *cp; 733 0 stevel 734 0 stevel #ifdef TRACE 735 0 stevel tprintf("TRACE- search()\n"); 736 0 stevel #endif 737 0 stevel Stype = type; Sgoal = goal; 738 0 stevel if (type == ZGOTO) { 739 0 stevel bseek((off_t)0); 740 0 stevel } 741 0 stevel do { 742 0 stevel if (intty && fseekp == feobp) { 743 0 stevel printf("? "), flush(); 744 0 stevel } 745 0 stevel aword[0] = 0; 746 0 stevel (void) getword(aword); 747 0 stevel 748 0 stevel switch (srchx(aword)) { 749 0 stevel 750 0 stevel case ZELSE: 751 0 stevel if (level == 0 && type == ZIF) { 752 0 stevel return; 753 0 stevel } 754 0 stevel break; 755 0 stevel 756 0 stevel case ZIF: 757 0 stevel while (getword(aword)) { 758 0 stevel continue; 759 0 stevel } 760 0 stevel if ((type == ZIF || type == ZELSE) && 761 0 stevel eq(aword, S_then)) { 762 0 stevel level++; 763 0 stevel } 764 0 stevel break; 765 0 stevel 766 0 stevel case ZENDIF: 767 0 stevel if (type == ZIF || type == ZELSE) { 768 0 stevel level--; 769 0 stevel } 770 0 stevel break; 771 0 stevel 772 0 stevel case ZFOREACH: 773 0 stevel case ZWHILE: 774 0 stevel if (type == ZBREAK) { 775 0 stevel level++; 776 0 stevel } 777 0 stevel break; 778 0 stevel 779 0 stevel case ZEND: 780 0 stevel if (type == ZBREAK) { 781 0 stevel level--; 782 0 stevel } 783 0 stevel break; 784 0 stevel 785 0 stevel case ZSWITCH: 786 0 stevel if (type == ZSWITCH || type == ZBRKSW) { 787 0 stevel level++; 788 0 stevel } 789 0 stevel break; 790 0 stevel 791 0 stevel case ZENDSW: 792 0 stevel if (type == ZSWITCH || type == ZBRKSW) { 793 0 stevel level--; 794 0 stevel } 795 0 stevel break; 796 0 stevel 797 0 stevel case ZLABEL: 798 0 stevel if (type == ZGOTO && getword(aword) && 799 0 stevel eq(aword, goal)) { 800 0 stevel level = -1; 801 0 stevel } 802 0 stevel break; 803 0 stevel 804 0 stevel default: 805 0 stevel if (type != ZGOTO && (type != ZSWITCH || level != 0)) { 806 0 stevel break; 807 0 stevel } 808 0 stevel if (lastchr(aword) != ':') { 809 0 stevel break; 810 0 stevel } 811 0 stevel aword[strlen_(aword) - 1] = 0; 812 0 stevel if (type == ZGOTO && eq(aword, goal) || 813 0 stevel type == ZSWITCH && eq(aword, S_default)) { 814 0 stevel level = -1; 815 0 stevel } 816 0 stevel break; 817 0 stevel 818 0 stevel case ZCASE: 819 0 stevel if (type != ZSWITCH || level != 0) { 820 0 stevel break; 821 0 stevel } 822 0 stevel (void) getword(aword); 823 0 stevel if (lastchr(aword) == ':') { 824 0 stevel aword[strlen_(aword) - 1] = 0; 825 0 stevel } 826 0 stevel cp = strip(Dfix1(aword)); 827 0 stevel if (Gmatch(goal, cp)) { 828 0 stevel level = -1; 829 0 stevel } 830 0 stevel xfree(cp); 831 0 stevel break; 832 0 stevel 833 0 stevel case ZDEFAULT: 834 0 stevel if (type == ZSWITCH && level == 0) { 835 0 stevel level = -1; 836 0 stevel } 837 0 stevel break; 838 0 stevel } 839 0 stevel (void) getword(NOSTR); 840 0 stevel } while (level >= 0); 841 0 stevel } 842 0 stevel 843 0 stevel int 844 0 stevel getword(tchar *wp) 845 0 stevel { 846 0 stevel int found = 0; 847 0 stevel int c, d; 848 0 stevel #ifdef TRACE 849 0 stevel tprintf("TRACE- getword()\n"); 850 0 stevel #endif 851 0 stevel 852 0 stevel c = readc(1); 853 0 stevel d = 0; 854 0 stevel do { 855 0 stevel while (issp(c)) { 856 0 stevel c = readc(1); 857 0 stevel } 858 0 stevel if (c == '#') { 859 0 stevel do { 860 0 stevel c = readc(1); 861 0 stevel } while (c >= 0 && c != '\n'); 862 0 stevel } 863 0 stevel if (c < 0) { 864 0 stevel goto past; 865 0 stevel } 866 0 stevel if (c == '\n') { 867 0 stevel if (wp) { 868 0 stevel break; 869 0 stevel } 870 0 stevel return (0); 871 0 stevel } 872 0 stevel 873 0 stevel /* ( and ) form separate words */ 874 0 stevel if (c == '(' || c == ')') { 875 0 stevel return (1); 876 0 stevel } 877 0 stevel 878 0 stevel unreadc(c); 879 0 stevel found = 1; 880 0 stevel do { 881 0 stevel c = readc(1); 882 0 stevel if (c == '\\' && (c = readc(1)) == '\n') { 883 0 stevel c = ' '; 884 0 stevel } 885 0 stevel if (c == '\'' || c == '"') { 886 0 stevel if (d == 0) { 887 0 stevel d = c; 888 0 stevel } else if (d == c) { 889 0 stevel d = 0; 890 0 stevel } 891 0 stevel } 892 0 stevel if (c < 0) { 893 0 stevel goto past; 894 0 stevel } 895 0 stevel if (wp) { 896 0 stevel *wp++ = c; 897 0 stevel } 898 0 stevel } while ((d || !issp(c) && c != '(' && c != ')') && c != '\n'); 899 0 stevel } while (wp == 0); 900 0 stevel unreadc(c); 901 0 stevel if (found) { 902 0 stevel *--wp = 0; 903 0 stevel } 904 0 stevel return (found); 905 0 stevel 906 0 stevel past: 907 0 stevel switch (Stype) { 908 0 stevel 909 0 stevel case ZIF: 910 0 stevel bferr("then/endif not found"); 911 0 stevel 912 0 stevel case ZELSE: 913 0 stevel bferr("endif not found"); 914 0 stevel 915 0 stevel case ZBRKSW: 916 0 stevel case ZSWITCH: 917 0 stevel bferr("endsw not found"); 918 0 stevel 919 0 stevel case ZBREAK: 920 0 stevel bferr("end not found"); 921 0 stevel 922 0 stevel case ZGOTO: 923 0 stevel setname(Sgoal); 924 0 stevel bferr("label not found"); 925 0 stevel } 926 0 stevel /*NOTREACHED*/ 927 356 muffin 928 356 muffin return (0); 929 0 stevel } 930 0 stevel 931 0 stevel void 932 356 muffin toend(void) 933 0 stevel { 934 0 stevel 935 0 stevel #ifdef TRACE 936 0 stevel tprintf("TRACE- toend()\n"); 937 0 stevel #endif 938 0 stevel if (whyles->w_end == 0) { 939 0 stevel search(ZBREAK, 0); 940 0 stevel whyles->w_end = btell() - 1; 941 0 stevel } else { 942 0 stevel bseek(whyles->w_end); 943 0 stevel } 944 0 stevel wfree(); 945 0 stevel } 946 0 stevel 947 0 stevel void 948 356 muffin wfree(void) 949 0 stevel { 950 0 stevel long o = btell(); 951 0 stevel 952 0 stevel #ifdef TRACE 953 0 stevel tprintf("TRACE- wfree()\n"); 954 0 stevel #endif 955 0 stevel while (whyles) { 956 0 stevel struct whyle *wp = whyles; 957 0 stevel struct whyle *nwp = wp->w_next; 958 0 stevel 959 0 stevel if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end)) { 960 0 stevel break; 961 0 stevel } 962 0 stevel if (wp->w_fe0) { 963 0 stevel blkfree(wp->w_fe0); 964 0 stevel } 965 0 stevel if (wp->w_fename) { 966 0 stevel xfree(wp->w_fename); 967 0 stevel } 968 0 stevel xfree((char *)wp); 969 0 stevel whyles = nwp; 970 0 stevel } 971 0 stevel } 972 0 stevel 973 0 stevel void 974 0 stevel doecho(tchar **v) 975 0 stevel { 976 0 stevel 977 0 stevel #ifdef TRACE 978 0 stevel tprintf("TRACE- doecho()\n"); 979 0 stevel #endif 980 0 stevel echo(' ', v); 981 0 stevel } 982 0 stevel 983 0 stevel void 984 0 stevel doglob(tchar **v) 985 0 stevel { 986 0 stevel 987 0 stevel #ifdef TRACE 988 0 stevel tprintf("TRACE- doglob()\n"); 989 0 stevel #endif 990 0 stevel echo(0, v); 991 0 stevel flush(); 992 0 stevel } 993 0 stevel 994 0 stevel void 995 0 stevel echo(tchar sep, tchar **v) 996 0 stevel { 997 0 stevel tchar *cp; 998 0 stevel int nonl = 0; 999 0 stevel 1000 0 stevel #ifdef TRACE 1001 0 stevel tprintf("TRACE- echo()\n"); 1002 0 stevel #endif 1003 0 stevel if (setintr) { 1004 0 stevel (void) sigsetmask(sigblock(0) & ~sigmask(SIGINT)); 1005 0 stevel } 1006 0 stevel v++; 1007 0 stevel if (*v == 0) { 1008 0 stevel /* 1009 0 stevel * echo command needs to have newline when there are no 1010 0 stevel * flags or arguments. glob should have no newline. If 1011 0 stevel * the separator is a blank, we are doing an echo. If the 1012 0 stevel * separator is zero, we are globbing. 1013 0 stevel */ 1014 0 stevel if (sep == (tchar)' ') 1015 0 stevel Putchar('\n'); 1016 0 stevel return; 1017 0 stevel } 1018 0 stevel gflag = 0, tglob(v); 1019 0 stevel if (gflag) { 1020 0 stevel v = glob(v); 1021 0 stevel if (v == 0) { 1022 0 stevel bferr("No match"); 1023 0 stevel } 1024 0 stevel } 1025 0 stevel /* check for -n arg, NOTE: it might be quoted */ 1026 0 stevel if (sep == ' ' && *v && strlen_(*v) == 2 && 1027 0 stevel ((**v&TRIM) == '-' && (*(*v + 1) & TRIM) == 'n' && 1028 0 stevel (*(*v+2)&TRIM) == 0)) { 1029 0 stevel nonl++, v++; 1030 0 stevel } 1031 0 stevel while (cp = *v++) { 1032 0 stevel int c; 1033 0 stevel 1034 0 stevel while (c = *cp++) { 1035 0 stevel Putchar(c | QUOTE); 1036 0 stevel } 1037 0 stevel if (*v) { 1038 0 stevel Putchar(sep | QUOTE); 1039 0 stevel } 1040 0 stevel } 1041 0 stevel if (sep && nonl == 0) { 1042 0 stevel Putchar('\n'); 1043 0 stevel } else { 1044 0 stevel flush(); 1045 0 stevel } 1046 0 stevel if (setintr) { 1047 0 stevel (void) sigblock(sigmask(SIGINT)); 1048 0 stevel } 1049 0 stevel if (gargv) { 1050 0 stevel blkfree(gargv), gargv = 0; 1051 0 stevel } 1052 0 stevel } 1053 0 stevel 1054 0 stevel extern char **environ; 1055 0 stevel 1056 0 stevel /* 1057 0 stevel * Check if the environment variable vp affects this csh's behavior 1058 0 stevel * and therefore we should call setlocale() or not. 1059 0 stevel * This function has two side effects when it returns 1: 1060 0 stevel * variable islocalevar_catnum is set to the LC_xxx value. 1061 0 stevel * variable islocalevar_catname is set to the string "LC_xxx" 1062 0 stevel */ 1063 0 stevel static int islocalevar_catnum; 1064 0 stevel static char *islocalevar_catname; 1065 0 stevel 1066 0 stevel static 1067 0 stevel bool 1068 0 stevel islocalevar(tchar *vp) 1069 0 stevel { 1070 0 stevel static struct lcinfo { 1071 0 stevel tchar * evname; /* The name of the env. var. */ 1072 0 stevel } categories_we_care[] = { 1073 0 stevel S_LANG, S_LC_ALL, S_LC_CTYPE, S_LC_MESSAGES, 1074 0 stevel NOSTR /* assumption: LC_xxx >= 0 */ 1075 0 stevel }; 1076 0 stevel struct lcinfo *p = categories_we_care; 1077 0 stevel 1078 0 stevel do { 1079 0 stevel if (strcmp_(vp, p->evname) == 0) { 1080 0 stevel return (1); 1081 0 stevel } 1082 0 stevel } while (((++p)->evname) != NOSTR); 1083 0 stevel return (0); 1084 0 stevel } 1085 0 stevel 1086 0 stevel void 1087 0 stevel dosetenv(tchar **v) 1088 0 stevel { 1089 0 stevel tchar *vp, *lp; 1090 0 stevel 1091 0 stevel #ifdef TRACE 1092 0 stevel tprintf("TRACE- dosetenv()\n"); 1093 0 stevel #endif 1094 0 stevel v++; 1095 0 stevel if ((vp = *v++) == 0) { 1096 0 stevel char **ep; 1097 0 stevel 1098 0 stevel if (setintr) { 1099 0 stevel (void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT)); 1100 0 stevel } 1101 0 stevel for (ep = environ; *ep; ep++) { 1102 0 stevel printf("%s\n", *ep); 1103 0 stevel } 1104 0 stevel return; 1105 0 stevel } 1106 0 stevel 1107 0 stevel if ((lp = *v++) == 0) { 1108 0 stevel lp = S_; /* "" */ 1109 0 stevel } 1110 0 stevel local_setenv(vp, lp = globone(lp)); 1111 0 stevel if (eq(vp, S_PATH)) { 1112 0 stevel importpath(lp); 1113 0 stevel dohash(xhash); 1114 0 stevel } else if (islocalevar(vp)) { 1115 0 stevel if (!setlocale(LC_ALL, "")) { 1116 0 stevel error("Locale could not be set properly"); 1117 0 stevel } 1118 0 stevel } 1119 0 stevel 1120 0 stevel xfree(lp); 1121 0 stevel } 1122 0 stevel 1123 0 stevel void 1124 0 stevel dounsetenv(tchar **v) 1125 0 stevel { 1126 0 stevel #ifdef TRACE 1127 0 stevel tprintf("TRACE- dounsetenv()\n"); 1128 0 stevel #endif 1129 0 stevel v++; 1130 0 stevel do { 1131 0 stevel local_unsetenv(*v); 1132 0 stevel if (islocalevar(*v++)) { 1133 0 stevel setlocale(LC_ALL, ""); /* Hope no error! */ 1134 0 stevel } 1135 0 stevel } while (*v); 1136 0 stevel } 1137 0 stevel 1138 0 stevel void 1139 0 stevel local_setenv(tchar *name, tchar *val) 1140 0 stevel { 1141 0 stevel char **ep = environ; 1142 0 stevel tchar *cp; 1143 0 stevel char *dp; 1144 0 stevel tchar *ep_; /* temporary */ 1145 0 stevel char *blk[2], **oep = ep; 1146 0 stevel 1147 0 stevel #ifdef TRACE 1148 0 stevel /* tprintf("TRACE- local_setenv(%t, %t)\n", name, val); */ 1149 0 stevel /* printf("IN local_setenv args = (%t)\n", val); */ 1150 0 stevel #endif 1151 0 stevel for (; *ep; ep++) { 1152 0 stevel #ifdef MBCHAR 1153 0 stevel for (cp = name, dp = *ep; *cp && *dp; cp++) { 1154 0 stevel /* 1155 0 stevel * This loop compares two chars in different 1156 0 stevel * representations, EUC (as char *) and wchar_t 1157 0 stevel * (in tchar), and ends when they are different. 1158 0 stevel */ 1159 0 stevel wchar_t dwc; 1160 0 stevel int n; 1161 0 stevel 1162 0 stevel n = mbtowc(&dwc, dp, MB_CUR_MAX); 1163 0 stevel if (n <= 0) { 1164 0 stevel break; /* Illegal multibyte. */ 1165 0 stevel } 1166 0 stevel dp += n; /* Advance to next multibyte char. */ 1167 0 stevel if (dwc == (wchar_t)(*cp & TRIM)) { 1168 0 stevel continue; 1169 0 stevel } else { 1170 0 stevel break; 1171 0 stevel } 1172 0 stevel } 1173 0 stevel #else /* !MBCHAR */ 1174 0 stevel for (cp = name, dp = *ep; *cp && (char)*cp == *dp; cp++, dp++) { 1175 0 stevel continue; 1176 0 stevel } 1177 0 stevel #endif /* !MBCHAR */ 1178 0 stevel if (*cp != 0 || *dp != '=') { 1179 0 stevel continue; 1180 0 stevel } 1181 0 stevel cp = strspl(S_EQ, val); 1182 0 stevel xfree(*ep); 1183 0 stevel ep_ = strspl(name, cp); /* ep_ is xalloc'ed */ 1184 0 stevel xfree(cp); 1185 0 stevel /* 1186 0 stevel * Trimming is not needed here. 1187 0 stevel * trim(); 1188 0 stevel */ 1189 0 stevel *ep = tstostr(NULL, ep_); 1190 0 stevel xfree(ep_); /* because temp. use */ 1191 0 stevel return; 1192 0 stevel } 1193 0 stevel ep_ = strspl(name, S_EQ); /* ep_ is xalloc'ed */ 1194 0 stevel blk[0] = tstostr(NULL, ep_); 1195 0 stevel blk[1] = 0; 1196 0 stevel xfree(ep_); 1197 356 muffin environ = (char **)blkspl_((char **)environ, blk); 1198 0 stevel xfree((void *)oep); 1199 0 stevel local_setenv(name, val); 1200 0 stevel } 1201 0 stevel 1202 0 stevel void 1203 0 stevel local_unsetenv(tchar *name) 1204 0 stevel { 1205 0 stevel char **ep = environ; 1206 0 stevel tchar *cp; 1207 0 stevel char *dp; 1208 0 stevel char **oep = ep; 1209 0 stevel char *cp_; /* tmp use */ 1210 356 muffin static int cnt = 0; /* delete counter */ 1211 0 stevel 1212 0 stevel #ifdef TRACE 1213 0 stevel tprintf("TRACE- local_unsetenv()\n"); 1214 0 stevel #endif 1215 0 stevel for (; *ep; ep++) { 1216 0 stevel #ifdef MBCHAR 1217 0 stevel for (cp = name, dp = *ep; *cp && *dp; cp++) { 1218 0 stevel /* 1219 0 stevel * This loop compares two chars in different 1220 0 stevel * representations, EUC (as char *) and wchar_t 1221 0 stevel * (in tchar), and ends when they are different. 1222 0 stevel */ 1223 0 stevel wchar_t dwc; 1224 0 stevel int n; 1225 0 stevel 1226 0 stevel n = mbtowc(&dwc, dp, MB_CUR_MAX); 1227 0 stevel if (n <= 0) { 1228 0 stevel break; /* Illegal multibyte. */ 1229 0 stevel } 1230 0 stevel dp += n; /* Advance to next multibyte char. */ 1231 0 stevel if (dwc == (wchar_t)(*cp & TRIM)) { 1232 0 stevel continue; 1233 0 stevel } else { 1234 0 stevel break; 1235 0 stevel } 1236 0 stevel } 1237 0 stevel #else /* !MBCHAR */ 1238 0 stevel for (cp = name, dp = *ep; *cp && (char)*cp == *dp; cp++, dp++) { 1239 0 stevel continue; 1240 0 stevel } 1241 0 stevel #endif /* !MBCHAR */ 1242 0 stevel if (*cp != 0 || *dp != '=') { 1243 0 stevel continue; 1244 0 stevel } 1245 0 stevel cp_ = *ep; 1246 0 stevel *ep = 0; 1247 356 muffin environ = (char **)blkspl_((char **)environ, ep+1); 1248 0 stevel *ep = cp_; 1249 0 stevel xfree(cp_); 1250 0 stevel xfree((void *)oep); 1251 0 stevel return; 1252 0 stevel } 1253 0 stevel } 1254 0 stevel 1255 0 stevel void 1256 0 stevel doumask(tchar **v) 1257 0 stevel { 1258 0 stevel tchar *cp = v[1]; 1259 0 stevel int i; 1260 0 stevel 1261 0 stevel #ifdef TRACE 1262 0 stevel tprintf("TRACE- dounmask()\n"); 1263 0 stevel #endif 1264 0 stevel if (cp == 0) { 1265 0 stevel i = umask(0); 1266 0 stevel (void) umask(i); 1267 0 stevel printf("%o\n", i); 1268 0 stevel return; 1269 0 stevel } 1270 0 stevel i = 0; 1271 0 stevel while (digit(*cp) && *cp != '8' && *cp != '9') { 1272 0 stevel i = i * 8 + *cp++ - '0'; 1273 0 stevel } 1274 0 stevel if (*cp || i < 0 || i > 0777) { 1275 0 stevel bferr("Improper mask"); 1276 0 stevel } 1277 0 stevel (void) umask(i); 1278 0 stevel } 1279 0 stevel 1280 0 stevel 1281 0 stevel struct limits * 1282 0 stevel findlim(tchar *cp) 1283 0 stevel { 1284 0 stevel struct limits *lp, *res; 1285 0 stevel 1286 0 stevel #ifdef TRACE 1287 0 stevel tprintf("TRACE- findlim()\n"); 1288 0 stevel #endif 1289 0 stevel res = 0; 1290 0 stevel for (lp = limits; lp->limconst >= 0; lp++) { 1291 0 stevel if (prefix(cp, lp->limname)) { 1292 0 stevel if (res) { 1293 0 stevel bferr("Ambiguous"); 1294 0 stevel } 1295 0 stevel res = lp; 1296 0 stevel } 1297 0 stevel } 1298 0 stevel if (res) { 1299 0 stevel return (res); 1300 0 stevel } 1301 0 stevel bferr("No such limit"); 1302 0 stevel /*NOTREACHED*/ 1303 0 stevel } 1304 0 stevel 1305 0 stevel void 1306 0 stevel dolimit(tchar **v) 1307 0 stevel { 1308 0 stevel struct limits *lp; 1309 0 stevel rlim_t limit; 1310 0 stevel tchar hard = 0; 1311 0 stevel 1312 0 stevel #ifdef TRACE 1313 0 stevel tprintf("TRACE- dolimit()\n"); 1314 0 stevel #endif 1315 0 stevel v++; 1316 0 stevel if (*v && eq(*v, S_h)) { 1317 0 stevel hard = 1; 1318 0 stevel v++; 1319 0 stevel } 1320 0 stevel if (*v == 0) { 1321 0 stevel for (lp = limits; lp->limconst >= 0; lp++) { 1322 0 stevel plim(lp, hard); 1323 0 stevel } 1324 0 stevel return; 1325 0 stevel } 1326 0 stevel lp = findlim(v[0]); 1327 0 stevel if (v[1] == 0) { 1328 0 stevel plim(lp, hard); 1329 0 stevel return; 1330 0 stevel } 1331 0 stevel switch (getval(lp, v+1, &limit)) { 1332 0 stevel case 0: 1333 0 stevel error("Value specified for limit is too large"); 1334 0 stevel return; 1335 0 stevel case (-1): 1336 0 stevel error("Numeric conversion failed"); 1337 0 stevel return; 1338 0 stevel default: 1339 0 stevel if (setlim(lp, hard, limit) < 0) { 1340 0 stevel error(NOSTR); 1341 0 stevel } 1342 0 stevel } 1343 0 stevel } 1344 0 stevel 1345 0 stevel static int 1346 0 stevel getval(struct limits *lp, tchar **v, rlim_t *retval) 1347 0 stevel { 1348 0 stevel rlim_t value, tmp, tmp2; 1349 0 stevel tchar *cp = *v++; 1350 0 stevel char chbuf[BUFSIZ * MB_LEN_MAX]; 1351 0 stevel 1352 0 stevel #ifdef TRACE 1353 0 stevel tprintf("TRACE- getval()\n"); 1354 0 stevel #endif 1355 0 stevel 1356 0 stevel tstostr(chbuf, cp); 1357 0 stevel errno = 0; 1358 0 stevel value = strtoull(chbuf, NULL, 0); 1359 0 stevel /* 1360 0 stevel * we must accept zero, but the conversion can fail and give us 1361 0 stevel * zero as well...try to deal with it as gracefully as possible 1362 0 stevel * by checking for EINVAL 1363 0 stevel */ 1364 0 stevel if (value == 0 && errno == EINVAL) 1365 0 stevel return (-1); 1366 0 stevel 1367 0 stevel while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') { 1368 0 stevel cp++; 1369 0 stevel } 1370 0 stevel if (*cp == 0) { 1371 0 stevel if (*v == 0) { 1372 0 stevel tmp = value * (rlim_t)lp->limdiv; 1373 0 stevel /* Check for overflow */ 1374 0 stevel if (tmp >= value) { 1375 0 stevel *retval = tmp; 1376 0 stevel return (1); 1377 0 stevel } else { 1378 0 stevel return (0); 1379 0 stevel } 1380 0 stevel } 1381 0 stevel cp = *v; 1382 0 stevel } 1383 0 stevel switch (*cp) { 1384 0 stevel 1385 0 stevel case ':': 1386 0 stevel if (lp->limconst != RLIMIT_CPU) { 1387 0 stevel goto badscal; 1388 0 stevel } 1389 0 stevel tstostr(chbuf, cp + 1); 1390 0 stevel tmp = strtoull(chbuf, NULL, 0); 1391 0 stevel tmp2 = value * 60 + tmp; 1392 0 stevel if (tmp2 >= value) { 1393 0 stevel *retval = tmp2; 1394 0 stevel return (1); 1395 0 stevel } else { 1396 0 stevel return (0); 1397 0 stevel } 1398 0 stevel 1399 0 stevel case 'h': 1400 0 stevel if (lp->limconst != RLIMIT_CPU) { 1401 0 stevel goto badscal; 1402 0 stevel } 1403 0 stevel limtail(cp, S_hours); 1404 0 stevel tmp = value * 3600; 1405 0 stevel if (tmp < value) { 1406 0 stevel return (0); 1407 0 stevel } 1408 0 stevel value = tmp; 1409 0 stevel break; 1410 0 stevel 1411 0 stevel case 'm': 1412 0 stevel if (lp->limconst == RLIMIT_CPU) { 1413 0 stevel limtail(cp, S_minutes); 1414 0 stevel tmp = value * 60; 1415 0 stevel if (tmp < value) { 1416 0 stevel return (0); 1417 0 stevel } 1418 0 stevel value = tmp; 1419 0 stevel break; 1420 0 stevel } 1421 0 stevel case 'M': 1422 0 stevel if (lp->limconst == RLIMIT_CPU) { 1423 0 stevel goto badscal; 1424 0 stevel } 1425 0 stevel *cp = 'm'; 1426 0 stevel limtail(cp, S_megabytes); 1427 0 stevel tmp = value * 1024 * 1024; 1428 0 stevel if (tmp < value) { 1429 0 stevel return (0); 1430 0 stevel } 1431 0 stevel value = tmp; 1432 0 stevel break; 1433 0 stevel 1434 0 stevel case 's': 1435 0 stevel if (lp->limconst != RLIMIT_CPU) { 1436 0 stevel goto badscal; 1437 0 stevel } 1438 0 stevel limtail(cp, S_seconds); 1439 0 stevel break; 1440 0 stevel 1441 0 stevel case 'k': 1442 0 stevel if (lp->limconst == RLIMIT_CPU) { 1443 0 stevel goto badscal; 1444 0 stevel } 1445 0 stevel limtail(cp, S_kbytes); 1446 0 stevel tmp = value * 1024; 1447 0 stevel if (tmp < value) { 1448 0 stevel return (0); 1449 0 stevel } 1450 0 stevel value = tmp; 1451 0 stevel break; 1452 0 stevel 1453 0 stevel case 'u': 1454 0 stevel limtail(cp, S_unlimited); 1455 0 stevel *retval = RLIM_INFINITY; 1456 0 stevel return (1); 1457 0 stevel 1458 0 stevel default: 1459 0 stevel badscal: 1460 0 stevel bferr("Improper or unknown scale factor"); 1461 0 stevel } 1462 0 stevel *retval = value; 1463 0 stevel return (1); 1464 0 stevel } 1465 0 stevel 1466 0 stevel void 1467 0 stevel limtail(tchar *cp, tchar *str0) 1468 0 stevel { 1469 0 stevel tchar *str = str0; 1470 0 stevel #ifdef TRACE 1471 0 stevel tprintf("TRACE- limtail()\n"); 1472 0 stevel #endif 1473 0 stevel 1474 0 stevel while (*cp && *cp == *str) { 1475 0 stevel cp++, str++; 1476 0 stevel } 1477 0 stevel if (*cp) { 1478 0 stevel error("Bad scaling; did you mean ``%t''?", str0); 1479 0 stevel } 1480 0 stevel } 1481 0 stevel 1482 0 stevel void 1483 0 stevel plim(struct limits *lp, tchar hard) 1484 0 stevel { 1485 0 stevel struct rlimit rlim; 1486 0 stevel char buf[BUFSZ]; 1487 0 stevel char *pbuf; 1488 0 stevel rlim_t limit; 1489 0 stevel 1490 0 stevel #ifdef TRACE 1491 0 stevel tprintf("TRACE- plim()\n"); 1492 0 stevel #endif 1493 0 stevel printf("%t \t", lp->limname); 1494 0 stevel (void) getrlimit(lp->limconst, &rlim); 1495 0 stevel limit = hard ? rlim.rlim_max : rlim.rlim_cur; 1496 0 stevel if (limit == RLIM_INFINITY) { 1497 0 stevel printf("unlimited"); 1498 0 stevel } else if (lp->limconst == RLIMIT_CPU) { 1499 0 stevel psecs_ull(limit); 1500 0 stevel } else { 1501 0 stevel buf[BUFSZ - 1] = '\0'; 1502 0 stevel pbuf = ulltostr((limit / lp->limdiv), &buf[BUFSZ - 1]); 1503 0 stevel printf("%s %t", pbuf, lp->limscale); 1504 0 stevel } 1505 0 stevel printf("\n"); 1506 0 stevel } 1507 0 stevel 1508 0 stevel void 1509 0 stevel dounlimit(tchar **v) 1510 0 stevel { 1511 0 stevel struct limits *lp; 1512 0 stevel int err = 0; 1513 0 stevel tchar hard = 0; 1514 0 stevel #ifdef TRACE 1515 0 stevel tprintf("TRACE- dounlimit()\n"); 1516 0 stevel #endif 1517 0 stevel 1518 0 stevel v++; 1519 0 stevel if (*v && eq(*v, S_h)) { 1520 0 stevel hard = 1; 1521 0 stevel v++; 1522 0 stevel } 1523 0 stevel if (*v == 0) { 1524 0 stevel for (lp = limits; lp->limconst >= 0; lp++) { 1525 0 stevel if (setlim(lp, hard, RLIM_INFINITY) < 0) { 1526 0 stevel err++; 1527 0 stevel } 1528 0 stevel } 1529 0 stevel if (err) { 1530 0 stevel error(NULL); 1531 0 stevel } 1532 0 stevel return; 1533 0 stevel } 1534 0 stevel while (*v) { 1535 0 stevel lp = findlim(*v++); 1536 0 stevel if (setlim(lp, hard, RLIM_INFINITY) < 0) { 1537 0 stevel error(NULL); 1538 0 stevel } 1539 0 stevel } 1540 0 stevel } 1541 0 stevel 1542 0 stevel int 1543 0 stevel setlim(struct limits *lp, tchar hard, rlim_t limit) 1544 0 stevel { 1545 0 stevel struct rlimit rlim; 1546 0 stevel 1547 0 stevel #ifdef TRACE 1548 0 stevel tprintf("TRACE- setlim()\n"); 1549 0 stevel #endif 1550 0 stevel (void) getrlimit(lp->limconst, &rlim); 1551 0 stevel if (hard) { 1552 0 stevel rlim.rlim_max = limit; 1553 0 stevel } else if (limit == RLIM_INFINITY && geteuid() != 0) { 1554 0 stevel rlim.rlim_cur = rlim.rlim_max; 1555 0 stevel } else { 1556 0 stevel rlim.rlim_cur = limit; 1557 0 stevel } 1558 0 stevel if (setrlimit(lp->limconst, &rlim) < 0) { 1559 0 stevel printf("%t: %t: Can't %s%s limit\n", bname, lp->limname, 1560 0 stevel limit == RLIM_INFINITY ? "remove" : "set", 1561 0 stevel hard ? " hard" : ""); 1562 0 stevel return (-1); 1563 0 stevel } 1564 0 stevel return (0); 1565 0 stevel } 1566 0 stevel 1567 0 stevel void 1568 0 stevel dosuspend() 1569 0 stevel { 1570 0 stevel int ctpgrp; 1571 0 stevel void (*old)(); 1572 0 stevel 1573 0 stevel #ifdef TRACE 1574 0 stevel tprintf("TRACE- dosuspend()\n"); 1575 0 stevel #endif 1576 0 stevel if (loginsh) { 1577 0 stevel error("Can't suspend a login shell (yet)"); 1578 0 stevel } 1579 0 stevel if (getpid() == getsid(0)) { 1580 0 stevel error("Can't suspend this shell"); 1581 0 stevel } 1582 0 stevel untty(); 1583 0 stevel old = (void (*)())signal(SIGTSTP, SIG_DFL); 1584 0 stevel (void) kill(0, SIGTSTP); 1585 0 stevel /* the shell stops here */ 1586 0 stevel (void) signal(SIGTSTP, old); 1587 0 stevel if (tpgrp != -1) { 1588 0 stevel retry: 1589 0 stevel (void) ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp); 1590 0 stevel if (ctpgrp != opgrp) { 1591 0 stevel old = (void (*)())signal(SIGTTIN, SIG_DFL); 1592 0 stevel (void) kill(0, SIGTTIN); 1593 0 stevel (void) signal(SIGTTIN, old); 1594 0 stevel goto retry; 1595 0 stevel } 1596 0 stevel (void) setpgid(0, shpgrp); 1597 0 stevel (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&shpgrp); 1598 0 stevel } 1599 0 stevel } 1600 0 stevel 1601 0 stevel void 1602 0 stevel doeval(tchar **v) 1603 0 stevel { 1604 0 stevel tchar **oevalvec = evalvec; 1605 0 stevel tchar *oevalp = evalp; 1606 0 stevel jmp_buf osetexit; 1607 0 stevel int reenter; 1608 0 stevel tchar **gv = 0; 1609 0 stevel 1610 0 stevel #ifdef TRACE 1611 0 stevel tprintf("TRACE- doeval()\n"); 1612 0 stevel #endif 1613 0 stevel v++; 1614 0 stevel if (*v == 0) { 1615 0 stevel return; 1616 0 stevel } 1617 0 stevel gflag = 0, tglob(v); 1618 0 stevel if (gflag) { 1619 0 stevel gv = v = glob(v); 1620 0 stevel gargv = 0; 1621 0 stevel if (v == 0) { 1622 0 stevel error("No match"); 1623 0 stevel } 1624 0 stevel v = copyblk(v); 1625 0 stevel } else { 1626 0 stevel trim(v); 1627 0 stevel } 1628 0 stevel getexit(osetexit); 1629 0 stevel reenter = 0; 1630 0 stevel setexit(); 1631 0 stevel reenter++; 1632 0 stevel if (reenter == 1) { 1633 0 stevel evalvec = v; 1634 0 stevel evalp = 0; 1635 0 stevel process(0); 1636 0 stevel } 1637 0 stevel evalvec = oevalvec; 1638 0 stevel evalp = oevalp; 1639 0 stevel doneinp = 0; 1640 0 stevel if (gv) { 1641 0 stevel blkfree(gv); 1642 0 stevel } 1643 0 stevel resexit(osetexit); 1644 0 stevel if (reenter >= 2) { 1645 0 stevel error(NULL); 1646 0 stevel } 1647 0 stevel } 1648