sh.set.c revision 131962
1235783Skib/* $Header: /src/pub/tcsh/sh.set.c,v 3.48 2004/03/21 16:48:14 christos Exp $ */ 2235783Skib/* 3235783Skib * sh.set.c: Setting and Clearing of variables 4235783Skib */ 5235783Skib/*- 6235783Skib * Copyright (c) 1980, 1991 The Regents of the University of California. 7235783Skib * All rights reserved. 8235783Skib * 9235783Skib * Redistribution and use in source and binary forms, with or without 10235783Skib * modification, are permitted provided that the following conditions 11235783Skib * are met: 12235783Skib * 1. Redistributions of source code must retain the above copyright 13235783Skib * notice, this list of conditions and the following disclaimer. 14235783Skib * 2. Redistributions in binary form must reproduce the above copyright 15235783Skib * notice, this list of conditions and the following disclaimer in the 16235783Skib * documentation and/or other materials provided with the distribution. 17235783Skib * 3. Neither the name of the University nor the names of its contributors 18235783Skib * may be used to endorse or promote products derived from this software 19235783Skib * without specific prior written permission. 20235783Skib * 21235783Skib * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22235783Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23235783Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24235783Skib * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25235783Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26298951Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27235783Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28235783Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29268564Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30235783Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31235783Skib * SUCH DAMAGE. 32235783Skib */ 33235783Skib#include "sh.h" 34235783Skib 35235783SkibRCSID("$Id: sh.set.c,v 3.48 2004/03/21 16:48:14 christos Exp $") 36235783Skib 37235783Skib#include "ed.h" 38235783Skib#include "tw.h" 39235783Skib 40235783Skibextern Char HistLit; 41235783Skibextern bool GotTermCaps; 42235783Skibint numeof = 0; 43235783Skib 44280183Sdumbbellstatic void update_vars __P((Char *)); 45280183Sdumbbellstatic Char *getinx __P((Char *, int *)); 46280183Sdumbbellstatic void asx __P((Char *, int, Char *)); 47235783Skibstatic struct varent *getvx __P((Char *, int)); 48235783Skibstatic Char *xset __P((Char *, Char ***)); 49235783Skibstatic Char *operate __P((int, Char *, Char *)); 50235783Skibstatic void putn1 __P((int)); 51235783Skibstatic struct varent *madrof __P((Char *, struct varent *)); 52235783Skibstatic void unsetv1 __P((struct varent *)); 53235783Skibstatic void exportpath __P((Char **)); 54235783Skibstatic void balance __P((struct varent *, int, int)); 55235783Skib 56235783Skib/* 57235783Skib * C Shell 58235783Skib */ 59235783Skib 60235783Skibstatic void 61235783Skibupdate_vars(vp) 62235783Skib Char *vp; 63235783Skib{ 64235783Skib if (eq(vp, STRpath)) { 65235783Skib exportpath(adrof(STRpath)->vec); 66235783Skib dohash(NULL, NULL); 67235783Skib } 68235783Skib else if (eq(vp, STRhistchars)) { 69235783Skib register Char *pn = varval(vp); 70235783Skib 71235783Skib HIST = *pn++; 72235783Skib HISTSUB = *pn; 73235783Skib } 74235783Skib else if (eq(vp, STRpromptchars)) { 75235783Skib register Char *pn = varval(vp); 76235783Skib 77235783Skib PRCH = *pn++; 78235783Skib PRCHROOT = *pn; 79235783Skib } 80235783Skib else if (eq(vp, STRhistlit)) { 81235783Skib HistLit = 1; 82235783Skib } 83235783Skib else if (eq(vp, STRuser)) { 84235783Skib tsetenv(STRKUSER, varval(vp)); 85235783Skib tsetenv(STRLOGNAME, varval(vp)); 86235783Skib } 87235783Skib else if (eq(vp, STRgroup)) { 88235783Skib tsetenv(STRKGROUP, varval(vp)); 89235783Skib } 90235783Skib else if (eq(vp, STRwordchars)) { 91235783Skib word_chars = varval(vp); 92235783Skib } 93235783Skib else if (eq(vp, STRloginsh)) { 94235783Skib loginsh = 1; 95235783Skib } 96235783Skib else if (eq(vp, STRsymlinks)) { 97235783Skib register Char *pn = varval(vp); 98235783Skib 99235783Skib if (eq(pn, STRignore)) 100235783Skib symlinks = SYM_IGNORE; 101235783Skib else if (eq(pn, STRexpand)) 102235783Skib symlinks = SYM_EXPAND; 103235783Skib else if (eq(pn, STRchase)) 104235783Skib symlinks = SYM_CHASE; 105235783Skib else 106235783Skib symlinks = 0; 107235783Skib } 108235783Skib else if (eq(vp, STRterm)) { 109235783Skib Char *cp = varval(vp); 110235783Skib tsetenv(STRKTERM, cp); 111280183Sdumbbell#ifdef DOESNT_WORK_RIGHT 112235783Skib cp = getenv("TERMCAP"); 113235783Skib if (cp && (*cp != '/')) /* if TERMCAP and not a path */ 114235783Skib Unsetenv(STRTERMCAP); 115235783Skib#endif /* DOESNT_WORK_RIGHT */ 116235783Skib GotTermCaps = 0; 117235783Skib if (noediting && Strcmp(cp, STRnetwork) != 0 && 118235783Skib Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) { 119235783Skib editing = 1; 120235783Skib noediting = 0; 121235783Skib set(STRedit, Strsave(STRNULL), VAR_READWRITE); 122235783Skib } 123235783Skib ed_Init(); /* reset the editor */ 124235783Skib } 125235783Skib else if (eq(vp, STRhome)) { 126235783Skib Char *cp; 127235783Skib 128235783Skib cp = Strsave(varval(vp)); /* get the old value back */ 129235783Skib 130280183Sdumbbell /* 131235783Skib * convert to cononical pathname (possibly resolving symlinks) 132235783Skib */ 133235783Skib cp = dcanon(cp, cp); 134235783Skib 135235783Skib set(vp, Strsave(cp), VAR_READWRITE); /* have to save the new val */ 136235783Skib 137235783Skib /* and now mirror home with HOME */ 138235783Skib tsetenv(STRKHOME, cp); 139235783Skib /* fix directory stack for new tilde home */ 140235783Skib dtilde(); 141235783Skib xfree((ptr_t) cp); 142235783Skib } 143235783Skib else if (eq(vp, STRedit)) { 144235783Skib editing = 1; 145235783Skib noediting = 0; 146235783Skib /* PWP: add more stuff in here later */ 147235783Skib } 148235783Skib else if (eq(vp, STRshlvl)) { 149235783Skib tsetenv(STRKSHLVL, varval(vp)); 150235783Skib } 151249249Sdumbbell else if (eq(vp, STRignoreeof)) { 152296548Sdumbbell Char *cp; 153235783Skib numeof = 0; 154235783Skib for ((cp = varval(STRignoreeof)); cp && *cp; cp++) { 155235783Skib if (!Isdigit(*cp)) { 156235783Skib numeof = 0; 157235783Skib break; 158235783Skib } 159235783Skib numeof = numeof * 10 + *cp - '0'; 160235783Skib } 161235783Skib if (numeof <= 0) numeof = 26; /* Sanity check */ 162235783Skib } 163296548Sdumbbell else if (eq(vp, STRbackslash_quote)) { 164235783Skib bslash_quote = 1; 165235783Skib } 166235783Skib else if (eq(vp, STRdirstack)) { 167235783Skib dsetstack(); 168235783Skib } 169235783Skib else if (eq(vp, STRrecognize_only_executables)) { 170235783Skib tw_cmd_free(); 171235783Skib } 172280183Sdumbbell else if (eq(vp, STRkillring)) { 173235783Skib SetKillRing(getn(varval(vp))); 174235783Skib } 175235783Skib#ifndef HAVENOUTMP 176235783Skib else if (eq(vp, STRwatch)) { 177235783Skib resetwatch(); 178235783Skib } 179235783Skib#endif /* HAVENOUTMP */ 180235783Skib else if (eq(vp, STRimplicitcd)) { 181235783Skib implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1); 182235783Skib } 183235783Skib#ifdef COLOR_LS_F 184235783Skib else if (eq(vp, STRcolor)) { 185235783Skib set_color_context(); 186235783Skib } 187235783Skib#endif /* COLOR_LS_F */ 188280183Sdumbbell#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 189235783Skib else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) { 190235783Skib update_dspmbyte_vars(); 191235783Skib } 192235783Skib#endif 193235783Skib#ifdef NLS_CATALOGS 194235783Skib else if (eq(vp, STRcatalog)) { 195235783Skib (void) catclose(catd); 196235783Skib nlsinit(); 197235783Skib } 198235783Skib#if defined(FILEC) && defined(TIOCSTI) 199235783Skib else if (eq(vp, STRfilec)) 200235783Skib filec = 1; 201235783Skib#endif 202235783Skib#endif /* NLS_CATALOGS */ 203235783Skib} 204235783Skib 205235783Skib 206235783Skib/*ARGSUSED*/ 207235783Skibvoid 208235783Skibdoset(v, c) 209235783Skib register Char **v; 210235783Skib struct command *c; 211235783Skib{ 212235783Skib register Char *p; 213235783Skib Char *vp, op; 214235783Skib Char **vecp; 215235783Skib bool hadsub; 216235783Skib int subscr; 217235783Skib int flags = VAR_READWRITE; 218235783Skib bool first_match = 0; 219235783Skib bool last_match = 0; 220235783Skib bool changed = 0; 221235783Skib 222235783Skib USE(c); 223235783Skib v++; 224235783Skib do { 225235783Skib changed = 0; 226235783Skib /* 227235783Skib * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov> 228235783Skib */ 229235783Skib if (*v && eq(*v, STRmr)) { 230235783Skib flags = VAR_READONLY; 231235783Skib v++; 232235783Skib changed = 1; 233235783Skib } 234235783Skib if (*v && eq(*v, STRmf) && !last_match) { 235235783Skib first_match = 1; 236235783Skib v++; 237235783Skib changed = 1; 238235783Skib } 239235783Skib if (*v && eq(*v, STRml) && !first_match) { 240235783Skib last_match = 1; 241235783Skib v++; 242235783Skib changed = 1; 243235783Skib } 244235783Skib } while(changed); 245235783Skib p = *v++; 246235783Skib if (p == 0) { 247235783Skib plist(&shvhed, flags); 248235783Skib return; 249235783Skib } 250235783Skib do { 251235783Skib hadsub = 0; 252235783Skib vp = p; 253235783Skib if (letter(*p)) 254235783Skib for (; alnum(*p); p++) 255235783Skib continue; 256235783Skib if (vp == p || !letter(*vp)) 257235783Skib stderror(ERR_NAME | ERR_VARBEGIN); 258235783Skib if ((p - vp) > MAXVARLEN) { 259235783Skib stderror(ERR_NAME | ERR_VARTOOLONG); 260280183Sdumbbell return; 261235783Skib } 262235783Skib if (*p == '[') { 263235783Skib hadsub++; 264235783Skib p = getinx(p, &subscr); 265235783Skib } 266254819Sdumbbell if ((op = *p) != 0) { 267235783Skib *p++ = 0; 268235783Skib if (*p == 0 && *v && **v == '(') 269235783Skib p = *v++; 270235783Skib } 271235783Skib else if (*v && eq(*v, STRequal)) { 272235783Skib op = '=', v++; 273235783Skib if (*v) 274235783Skib p = *v++; 275235783Skib } 276235783Skib if (op && op != '=') 277235783Skib stderror(ERR_NAME | ERR_SYNTAX); 278235783Skib if (eq(p, STRLparen)) { 279 register Char **e = v; 280 281 if (hadsub) 282 stderror(ERR_NAME | ERR_SYNTAX); 283 for (;;) { 284 if (!*e) 285 stderror(ERR_NAME | ERR_MISSING, ')'); 286 if (**e == ')') 287 break; 288 e++; 289 } 290 p = *e; 291 *e = 0; 292 vecp = saveblk(v); 293 if (first_match) 294 flags |= VAR_FIRST; 295 else if (last_match) 296 flags |= VAR_LAST; 297 298 set1(vp, vecp, &shvhed, flags); 299 *e = p; 300 v = e + 1; 301 } 302 else if (hadsub) 303 asx(vp, subscr, Strsave(p)); 304 else 305 set(vp, Strsave(p), flags); 306 update_vars(vp); 307 } while ((p = *v++) != NULL); 308} 309 310static Char * 311getinx(cp, ip) 312 register Char *cp; 313 register int *ip; 314{ 315 *ip = 0; 316 *cp++ = 0; 317 while (*cp && Isdigit(*cp)) 318 *ip = *ip * 10 + *cp++ - '0'; 319 if (*cp++ != ']') 320 stderror(ERR_NAME | ERR_SUBSCRIPT); 321 return (cp); 322} 323 324static void 325asx(vp, subscr, p) 326 Char *vp; 327 int subscr; 328 Char *p; 329{ 330 register struct varent *v = getvx(vp, subscr); 331 332 if (v->v_flags & VAR_READONLY) 333 stderror(ERR_READONLY|ERR_NAME, v->v_name); 334 xfree((ptr_t) v->vec[subscr - 1]); 335 v->vec[subscr - 1] = globone(p, G_APPEND); 336} 337 338static struct varent * 339getvx(vp, subscr) 340 Char *vp; 341 int subscr; 342{ 343 register struct varent *v = adrof(vp); 344 345 if (v == 0) 346 udvar(vp); 347 if (subscr < 1 || subscr > blklen(v->vec)) 348 stderror(ERR_NAME | ERR_RANGE); 349 return (v); 350} 351 352/*ARGSUSED*/ 353void 354dolet(v, dummy) 355 Char **v; 356 struct command *dummy; 357{ 358 register Char *p; 359 Char *vp, c, op; 360 bool hadsub; 361 int subscr; 362 363 USE(dummy); 364 v++; 365 p = *v++; 366 if (p == 0) { 367 prvars(); 368 return; 369 } 370 do { 371 hadsub = 0; 372 vp = p; 373 if (letter(*p)) 374 for (; alnum(*p); p++) 375 continue; 376 if (vp == p || !letter(*vp)) 377 stderror(ERR_NAME | ERR_VARBEGIN); 378 if ((p - vp) > MAXVARLEN) 379 stderror(ERR_NAME | ERR_VARTOOLONG); 380 if (*p == '[') { 381 hadsub++; 382 p = getinx(p, &subscr); 383 } 384 if (*p == 0 && *v) 385 p = *v++; 386 if ((op = *p) != 0) 387 *p++ = 0; 388 else 389 stderror(ERR_NAME | ERR_ASSIGN); 390 391 /* 392 * if there is no expression after the '=' then print a "Syntax Error" 393 * message - strike 394 */ 395 if (*p == '\0' && *v == NULL) 396 stderror(ERR_NAME | ERR_ASSIGN); 397 398 vp = Strsave(vp); 399 if (op == '=') { 400 c = '='; 401 p = xset(p, &v); 402 } 403 else { 404 c = *p++; 405 if (any("+-", c)) { 406 if (c != op || *p) 407 stderror(ERR_NAME | ERR_UNKNOWNOP); 408 p = Strsave(STR1); 409 } 410 else { 411 if (any("<>", op)) { 412 if (c != op) 413 stderror(ERR_NAME | ERR_UNKNOWNOP); 414 c = *p++; 415 stderror(ERR_NAME | ERR_SYNTAX); 416 } 417 if (c != '=') 418 stderror(ERR_NAME | ERR_UNKNOWNOP); 419 p = xset(p, &v); 420 } 421 } 422 if (op == '=') { 423 if (hadsub) 424 asx(vp, subscr, p); 425 else 426 set(vp, p, VAR_READWRITE); 427 } 428 else if (hadsub) { 429 struct varent *gv = getvx(vp, subscr); 430 431 asx(vp, subscr, operate(op, gv->vec[subscr - 1], p)); 432 } 433 else 434 set(vp, operate(op, varval(vp), p), VAR_READWRITE); 435 update_vars(vp); 436 xfree((ptr_t) vp); 437 if (c != '=') 438 xfree((ptr_t) p); 439 } while ((p = *v++) != NULL); 440} 441 442static Char * 443xset(cp, vp) 444 Char *cp, ***vp; 445{ 446 register Char *dp; 447 448 if (*cp) { 449 dp = Strsave(cp); 450 --(*vp); 451 xfree((ptr_t) ** vp); 452 **vp = dp; 453 } 454 return (putn(expr(vp))); 455} 456 457static Char * 458operate(op, vp, p) 459 int op; 460 Char *vp, *p; 461{ 462 Char opr[2]; 463 Char *vec[5]; 464 register Char **v = vec; 465 Char **vecp = v; 466 register int i; 467 468 if (op != '=') { 469 if (*vp) 470 *v++ = vp; 471 opr[0] = (Char) op; 472 opr[1] = 0; 473 *v++ = opr; 474 if (op == '<' || op == '>') 475 *v++ = opr; 476 } 477 *v++ = p; 478 *v++ = 0; 479 i = expr(&vecp); 480 if (*vecp) 481 stderror(ERR_NAME | ERR_EXPRESSION); 482 return (putn(i)); 483} 484 485static Char *putp, nbuf[50]; 486 487Char * 488putn(n) 489 register int n; 490{ 491 int num; 492 493 putp = nbuf; 494 if (n < 0) { 495 n = -n; 496 *putp++ = '-'; 497 } 498 num = 2; /* confuse lint */ 499 if (sizeof(int) == num && ((unsigned int) n) == 0x8000) { 500 *putp++ = '3'; 501 n = 2768; 502#ifdef pdp11 503 } 504#else /* !pdp11 */ 505 } 506 else { 507 num = 4; /* confuse lint */ 508 if (sizeof(int) == num && ((unsigned int) n) == 0x80000000) { 509 *putp++ = '2'; 510 n = 147483648; 511 } 512 } 513#endif /* pdp11 */ 514 putn1(n); 515 *putp = 0; 516 return (Strsave(nbuf)); 517} 518 519static void 520putn1(n) 521 register int n; 522{ 523 if (n > 9) 524 putn1(n / 10); 525 *putp++ = n % 10 + '0'; 526} 527 528int 529getn(cp) 530 register Char *cp; 531{ 532 register int n; 533 int sign; 534 535 if (!cp) /* PWP: extra error checking */ 536 stderror(ERR_NAME | ERR_BADNUM); 537 538 sign = 0; 539 if (cp[0] == '+' && cp[1]) 540 cp++; 541 if (*cp == '-') { 542 sign++; 543 cp++; 544 if (!Isdigit(*cp)) 545 stderror(ERR_NAME | ERR_BADNUM); 546 } 547 n = 0; 548 while (Isdigit(*cp)) 549 n = n * 10 + *cp++ - '0'; 550 if (*cp) 551 stderror(ERR_NAME | ERR_BADNUM); 552 return (sign ? -n : n); 553} 554 555Char * 556value1(var, head) 557 Char *var; 558 struct varent *head; 559{ 560 register struct varent *vp; 561 562 if (!var || !head) /* PWP: extra error checking */ 563 return (STRNULL); 564 565 vp = adrof1(var, head); 566 return ((vp == NULL || vp->vec == NULL || vp->vec[0] == NULL) ? 567 STRNULL : vp->vec[0]); 568} 569 570static struct varent * 571madrof(pat, vp) 572 Char *pat; 573 register struct varent *vp; 574{ 575 register struct varent *vp1; 576 577 for (vp = vp->v_left; vp; vp = vp->v_right) { 578 if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL) 579 return vp1; 580 if (Gmatch(vp->v_name, pat)) 581 return vp; 582 } 583 return vp; 584} 585 586struct varent * 587adrof1(name, v) 588 register Char *name; 589 register struct varent *v; 590{ 591 int cmp; 592 593 v = v->v_left; 594 while (v && ((cmp = *name - *v->v_name) != 0 || 595 (cmp = Strcmp(name, v->v_name)) != 0)) 596 if (cmp < 0) 597 v = v->v_left; 598 else 599 v = v->v_right; 600 return v; 601} 602 603/* 604 * The caller is responsible for putting value in a safe place 605 */ 606void 607set(var, val, flags) 608 Char *var, *val; 609 int flags; 610{ 611 register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **))); 612 613 vec[0] = val; 614 vec[1] = 0; 615 set1(var, vec, &shvhed, flags); 616} 617 618void 619set1(var, vec, head, flags) 620 Char *var, **vec; 621 struct varent *head; 622 int flags; 623{ 624 register Char **oldv = vec; 625 626 if ((flags & VAR_NOGLOB) == 0) { 627 gflag = 0; 628 tglob(oldv); 629 if (gflag) { 630 vec = globall(oldv); 631 if (vec == 0) { 632 blkfree(oldv); 633 stderror(ERR_NAME | ERR_NOMATCH); 634 return; 635 } 636 blkfree(oldv); 637 gargv = 0; 638 } 639 } 640 /* 641 * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com> 642 */ 643 if ( flags & (VAR_FIRST | VAR_LAST) ) { 644 /* 645 * Code for -f (VAR_FIRST) and -l (VAR_LAST) options. 646 * Method: 647 * Delete all duplicate words leaving "holes" in the word array (vec). 648 * Then remove the "holes", keeping the order of the words unchanged. 649 */ 650 if (vec && vec[0] && vec[1]) { /* more than one word ? */ 651 int i, j; 652 int num_items; 653 654 for (num_items = 0; vec[num_items]; num_items++) 655 continue; 656 if (flags & VAR_FIRST) { 657 /* delete duplications, keeping first occurance */ 658 for (i = 1; i < num_items; i++) 659 for (j = 0; j < i; j++) 660 /* If have earlier identical item, remove i'th item */ 661 if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { 662 free(vec[i]); 663 vec[i] = NULL; 664 break; 665 } 666 } else if (flags & VAR_LAST) { 667 /* delete duplications, keeping last occurance */ 668 for (i = 0; i < num_items - 1; i++) 669 for (j = i + 1; j < num_items; j++) 670 /* If have later identical item, remove i'th item */ 671 if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { 672 /* remove identical item (the first) */ 673 free(vec[i]); 674 vec[i] = NULL; 675 } 676 } 677 /* Compress items - remove empty items */ 678 for (j = i = 0; i < num_items; i++) 679 if (vec[i]) 680 vec[j++] = vec[i]; 681 682 /* NULL-fy remaining items */ 683 for (; j < num_items; j++) 684 vec[j] = NULL; 685 } 686 /* don't let the attribute propagate */ 687 flags &= ~(VAR_FIRST|VAR_LAST); 688 } 689 setq(var, vec, head, flags); 690} 691 692 693void 694setq(name, vec, p, flags) 695 Char *name, **vec; 696 register struct varent *p; 697 int flags; 698{ 699 register struct varent *c; 700 register int f; 701 702 f = 0; /* tree hangs off the header's left link */ 703 while ((c = p->v_link[f]) != 0) { 704 if ((f = *name - *c->v_name) == 0 && 705 (f = Strcmp(name, c->v_name)) == 0) { 706 if (c->v_flags & VAR_READONLY) 707 stderror(ERR_READONLY|ERR_NAME, c->v_name); 708 blkfree(c->vec); 709 c->v_flags = flags; 710 trim(c->vec = vec); 711 return; 712 } 713 p = c; 714 f = f > 0; 715 } 716 p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent)); 717 c->v_name = Strsave(name); 718 c->v_flags = flags; 719 c->v_bal = 0; 720 c->v_left = c->v_right = 0; 721 c->v_parent = p; 722 balance(p, f, 0); 723 trim(c->vec = vec); 724} 725 726/*ARGSUSED*/ 727void 728unset(v, c) 729 Char **v; 730 struct command *c; 731{ 732 bool did_roe, did_edit; 733 734 USE(c); 735 did_roe = adrof(STRrecognize_only_executables) != NULL; 736 did_edit = adrof(STRedit) != NULL; 737 unset1(v, &shvhed); 738 739#if defined(FILEC) && defined(TIOCSTI) 740 if (adrof(STRfilec) == 0) 741 filec = 0; 742#endif /* FILEC && TIOCSTI */ 743 744 if (adrof(STRhistchars) == 0) { 745 HIST = '!'; 746 HISTSUB = '^'; 747 } 748 if (adrof(STRignoreeof) == 0) 749 numeof = 0; 750 if (adrof(STRpromptchars) == 0) { 751 PRCH = '>'; 752 PRCHROOT = '#'; 753 } 754 if (adrof(STRhistlit) == 0) 755 HistLit = 0; 756 if (adrof(STRloginsh) == 0) 757 loginsh = 0; 758 if (adrof(STRwordchars) == 0) 759 word_chars = STR_WORD_CHARS; 760 if (adrof(STRedit) == 0) 761 editing = 0; 762 if (adrof(STRbackslash_quote) == 0) 763 bslash_quote = 0; 764 if (adrof(STRsymlinks) == 0) 765 symlinks = 0; 766 if (adrof(STRimplicitcd) == 0) 767 implicit_cd = 0; 768 if (adrof(STRkillring) == 0) 769 SetKillRing(0); 770 if (did_edit && noediting && adrof(STRedit) == 0) 771 noediting = 0; 772 if (did_roe && adrof(STRrecognize_only_executables) == 0) 773 tw_cmd_free(); 774#ifdef COLOR_LS_F 775 if (adrof(STRcolor) == 0) 776 set_color_context(); 777#endif /* COLOR_LS_F */ 778#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 779 update_dspmbyte_vars(); 780#endif 781#ifdef NLS_CATALOGS 782 (void) catclose(catd); 783 nlsinit(); 784#endif /* NLS_CATALOGS */ 785} 786 787void 788unset1(v, head) 789 register Char *v[]; 790 struct varent *head; 791{ 792 register struct varent *vp; 793 register int cnt; 794 795 while (*++v) { 796 cnt = 0; 797 while ((vp = madrof(*v, head)) != NULL) 798 if (vp->v_flags & VAR_READONLY) 799 stderror(ERR_READONLY|ERR_NAME, vp->v_name); 800 else 801 unsetv1(vp), cnt++; 802 if (cnt == 0) 803 setname(short2str(*v)); 804 } 805} 806 807void 808unsetv(var) 809 Char *var; 810{ 811 register struct varent *vp; 812 813 if ((vp = adrof1(var, &shvhed)) == 0) 814 udvar(var); 815 unsetv1(vp); 816} 817 818static void 819unsetv1(p) 820 register struct varent *p; 821{ 822 register struct varent *c, *pp; 823 register int f; 824 825 /* 826 * Free associated memory first to avoid complications. 827 */ 828 blkfree(p->vec); 829 xfree((ptr_t) p->v_name); 830 /* 831 * If p is missing one child, then we can move the other into where p is. 832 * Otherwise, we find the predecessor of p, which is guaranteed to have no 833 * right child, copy it into p, and move it's left child into it. 834 */ 835 if (p->v_right == 0) 836 c = p->v_left; 837 else if (p->v_left == 0) 838 c = p->v_right; 839 else { 840 for (c = p->v_left; c->v_right; c = c->v_right) 841 continue; 842 p->v_name = c->v_name; 843 p->v_flags = c->v_flags; 844 p->vec = c->vec; 845 p = c; 846 c = p->v_left; 847 } 848 849 /* 850 * Move c into where p is. 851 */ 852 pp = p->v_parent; 853 f = pp->v_right == p; 854 if ((pp->v_link[f] = c) != 0) 855 c->v_parent = pp; 856 /* 857 * Free the deleted node, and rebalance. 858 */ 859 xfree((ptr_t) p); 860 balance(pp, f, 1); 861} 862 863void 864setNS(cp) 865 Char *cp; 866{ 867 set(cp, Strsave(STRNULL), VAR_READWRITE); 868} 869 870/*ARGSUSED*/ 871void 872shift(v, c) 873 register Char **v; 874 struct command *c; 875{ 876 register struct varent *argv; 877 register Char *name; 878 879 USE(c); 880 v++; 881 name = *v; 882 if (name == 0) 883 name = STRargv; 884 else 885 (void) strip(name); 886 argv = adrof(name); 887 if (argv == NULL || argv->vec == NULL) 888 udvar(name); 889 if (argv->vec[0] == 0) 890 stderror(ERR_NAME | ERR_NOMORE); 891 lshift(argv->vec, 1); 892 update_vars(name); 893} 894 895static Char STRsep[2] = { PATHSEP, '\0' }; 896 897static void 898exportpath(val) 899 Char **val; 900{ 901 Char *exppath; 902 size_t exppath_size = BUFSIZE; 903 exppath = (Char *)xmalloc(sizeof(Char)*exppath_size); 904 905 exppath[0] = 0; 906 if (val) 907 while (*val) { 908 while (Strlen(*val) + Strlen(exppath) + 2 > exppath_size) { 909 if ((exppath 910 = (Char *)xrealloc(exppath, sizeof(Char)*(exppath_size *= 2))) 911 == NULL) { 912 xprintf(CGETS(18, 1, 913 "Warning: ridiculously long PATH truncated\n")); 914 break; 915 } 916 } 917 (void) Strcat(exppath, *val++); 918 if (*val == 0 || eq(*val, STRRparen)) 919 break; 920 (void) Strcat(exppath, STRsep); 921 } 922 tsetenv(STRKPATH, exppath); 923 free(exppath); 924} 925 926#ifndef lint 927 /* 928 * Lint thinks these have null effect 929 */ 930 /* macros to do single rotations on node p */ 931# define rright(p) (\ 932 t = (p)->v_left,\ 933 (t)->v_parent = (p)->v_parent,\ 934 (((p)->v_left = t->v_right) != NULL) ?\ 935 (t->v_right->v_parent = (p)) : 0,\ 936 (t->v_right = (p))->v_parent = t,\ 937 (p) = t) 938# define rleft(p) (\ 939 t = (p)->v_right,\ 940 ((t)->v_parent = (p)->v_parent,\ 941 ((p)->v_right = t->v_left) != NULL) ? \ 942 (t->v_left->v_parent = (p)) : 0,\ 943 (t->v_left = (p))->v_parent = t,\ 944 (p) = t) 945#else 946static struct varent * 947rleft(p) 948 struct varent *p; 949{ 950 return (p); 951} 952static struct varent * 953rright(p) 954 struct varent *p; 955{ 956 return (p); 957} 958 959#endif /* ! lint */ 960 961 962/* 963 * Rebalance a tree, starting at p and up. 964 * F == 0 means we've come from p's left child. 965 * D == 1 means we've just done a delete, otherwise an insert. 966 */ 967static void 968balance(p, f, d) 969 register struct varent *p; 970 register int f, d; 971{ 972 register struct varent *pp; 973 974#ifndef lint 975 register struct varent *t; /* used by the rotate macros */ 976#endif /* !lint */ 977 register int ff; 978#ifdef lint 979 ff = 0; /* Sun's lint is dumb! */ 980#endif 981 982 /* 983 * Ok, from here on, p is the node we're operating on; pp is it's parent; f 984 * is the branch of p from which we have come; ff is the branch of pp which 985 * is p. 986 */ 987 for (; (pp = p->v_parent) != 0; p = pp, f = ff) { 988 ff = pp->v_right == p; 989 if (f ^ d) { /* right heavy */ 990 switch (p->v_bal) { 991 case -1: /* was left heavy */ 992 p->v_bal = 0; 993 break; 994 case 0: /* was balanced */ 995 p->v_bal = 1; 996 break; 997 case 1: /* was already right heavy */ 998 switch (p->v_right->v_bal) { 999 case 1: /* sigle rotate */ 1000 pp->v_link[ff] = rleft(p); 1001 p->v_left->v_bal = 0; 1002 p->v_bal = 0; 1003 break; 1004 case 0: /* single rotate */ 1005 pp->v_link[ff] = rleft(p); 1006 p->v_left->v_bal = 1; 1007 p->v_bal = -1; 1008 break; 1009 case -1: /* double rotate */ 1010 (void) rright(p->v_right); 1011 pp->v_link[ff] = rleft(p); 1012 p->v_left->v_bal = 1013 p->v_bal < 1 ? 0 : -1; 1014 p->v_right->v_bal = 1015 p->v_bal > -1 ? 0 : 1; 1016 p->v_bal = 0; 1017 break; 1018 default: 1019 break; 1020 } 1021 break; 1022 default: 1023 break; 1024 } 1025 } 1026 else { /* left heavy */ 1027 switch (p->v_bal) { 1028 case 1: /* was right heavy */ 1029 p->v_bal = 0; 1030 break; 1031 case 0: /* was balanced */ 1032 p->v_bal = -1; 1033 break; 1034 case -1: /* was already left heavy */ 1035 switch (p->v_left->v_bal) { 1036 case -1: /* single rotate */ 1037 pp->v_link[ff] = rright(p); 1038 p->v_right->v_bal = 0; 1039 p->v_bal = 0; 1040 break; 1041 case 0: /* signle rotate */ 1042 pp->v_link[ff] = rright(p); 1043 p->v_right->v_bal = -1; 1044 p->v_bal = 1; 1045 break; 1046 case 1: /* double rotate */ 1047 (void) rleft(p->v_left); 1048 pp->v_link[ff] = rright(p); 1049 p->v_left->v_bal = 1050 p->v_bal < 1 ? 0 : -1; 1051 p->v_right->v_bal = 1052 p->v_bal > -1 ? 0 : 1; 1053 p->v_bal = 0; 1054 break; 1055 default: 1056 break; 1057 } 1058 break; 1059 default: 1060 break; 1061 } 1062 } 1063 /* 1064 * If from insert, then we terminate when p is balanced. If from 1065 * delete, then we terminate when p is unbalanced. 1066 */ 1067 if ((p->v_bal == 0) ^ d) 1068 break; 1069 } 1070} 1071 1072void 1073plist(p, what) 1074 register struct varent *p; 1075 int what; 1076{ 1077 register struct varent *c; 1078 register int len; 1079 1080 if (setintr) 1081#ifdef BSDSIGS 1082 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT)); 1083#else /* !BSDSIGS */ 1084 (void) sigrelse(SIGINT); 1085#endif /* BSDSIGS */ 1086 1087 for (;;) { 1088 while (p->v_left) 1089 p = p->v_left; 1090x: 1091 if (p->v_parent == 0) /* is it the header? */ 1092 return; 1093 if ((p->v_flags & what) != 0) { 1094 len = blklen(p->vec); 1095 xprintf("%S\t", p->v_name); 1096 if (len != 1) 1097 xputchar('('); 1098 blkpr(p->vec); 1099 if (len != 1) 1100 xputchar(')'); 1101 xputchar('\n'); 1102 } 1103 if (p->v_right) { 1104 p = p->v_right; 1105 continue; 1106 } 1107 do { 1108 c = p; 1109 p = p->v_parent; 1110 } while (p->v_right == c); 1111 goto x; 1112 } 1113} 1114 1115#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 1116bool dspmbyte_ls; 1117 1118void 1119update_dspmbyte_vars() 1120{ 1121 int lp, iskcode; 1122 Char *dstr1; 1123 struct varent *vp; 1124 1125 /* if variable "nokanji" is set, multi-byte display is disabled */ 1126 if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) { 1127 _enable_mbdisp = 1; 1128 dstr1 = vp->vec[0]; 1129 if(eq (dstr1, STRKSJIS)) 1130 iskcode = 1; 1131 else if (eq(dstr1, STRKEUC)) 1132 iskcode = 2; 1133 else if (eq(dstr1, STRKBIG5)) 1134 iskcode = 3; 1135 else if (eq(dstr1, STRKUTF8)) 1136 iskcode = 4; 1137 else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) { 1138 iskcode = 0; 1139 } 1140 else { 1141 xprintf(CGETS(18, 2, 1142 "Warning: unknown multibyte display; using default(euc(JP))\n")); 1143 iskcode = 2; 1144 } 1145 if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls)) 1146 dspmbyte_ls = 1; 1147 else 1148 dspmbyte_ls = 0; 1149 for (lp = 0; lp < 256 && iskcode > 0; lp++) { 1150 switch (iskcode) { 1151 case 1: 1152 /* Shift-JIS */ 1153 _cmap[lp] = _cmap_mbyte[lp]; 1154 _mbmap[lp] = _mbmap_sjis[lp]; 1155 break; 1156 case 2: 1157 /* 2 ... euc */ 1158 _cmap[lp] = _cmap_mbyte[lp]; 1159 _mbmap[lp] = _mbmap_euc[lp]; 1160 break; 1161 case 3: 1162 /* 3 ... big5 */ 1163 _cmap[lp] = _cmap_mbyte[lp]; 1164 _mbmap[lp] = _mbmap_big5[lp]; 1165 break; 1166 case 4: 1167 /* 4 ... utf8 */ 1168 _cmap[lp] = _cmap_mbyte[lp]; 1169 _mbmap[lp] = _mbmap_utf8[lp]; 1170 break; 1171 default: 1172 xprintf(CGETS(18, 3, 1173 "Warning: unknown multibyte code %d; multibyte disabled\n"), 1174 iskcode); 1175 _cmap[lp] = _cmap_c[lp]; 1176 _mbmap[lp] = 0; /* Default map all 0 */ 1177 _enable_mbdisp = 0; 1178 break; 1179 } 1180 } 1181 if (iskcode == 0) { 1182 /* check original table */ 1183 if (Strlen(dstr1) != 256) { 1184 xprintf(CGETS(18, 4, 1185 "Warning: Invalid multibyte table length (%d); multibyte disabled\n"), 1186 Strlen(dstr1)); 1187 _enable_mbdisp = 0; 1188 } 1189 for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) { 1190 if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) { 1191 xprintf(CGETS(18, 4, 1192 "Warning: bad multibyte code at offset +%d; multibyte diabled\n"), 1193 lp); 1194 _enable_mbdisp = 0; 1195 break; 1196 } 1197 } 1198 /* set original table */ 1199 for (lp = 0; lp < 256; lp++) { 1200 if (_enable_mbdisp == 1) { 1201 _cmap[lp] = _cmap_mbyte[lp]; 1202 _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f); 1203 } 1204 else { 1205 _cmap[lp] = _cmap_c[lp]; 1206 _mbmap[lp] = 0; /* Default map all 0 */ 1207 } 1208 } 1209 } 1210 } 1211 else { 1212 for (lp = 0; lp < 256; lp++) { 1213 _cmap[lp] = _cmap_c[lp]; 1214 _mbmap[lp] = 0; /* Default map all 0 */ 1215 } 1216 _enable_mbdisp = 0; 1217 dspmbyte_ls = 0; 1218 } 1219#ifdef MBYTEDEBUG /* Sorry, use for beta testing */ 1220 { 1221 Char mbmapstr[300]; 1222 for (lp = 0; lp < 256; lp++) { 1223 mbmapstr[lp] = _mbmap[lp] + '0'; 1224 mbmapstr[lp+1] = 0; 1225 } 1226 set(STRmbytemap, Strsave(mbmapstr), VAR_READWRITE); 1227 } 1228#endif /* MBYTEMAP */ 1229} 1230 1231/* dspkanji/dspmbyte autosetting */ 1232/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */ 1233void 1234autoset_dspmbyte(pcp) 1235 Char *pcp; 1236{ 1237 int i; 1238 struct dspm_autoset_Table { 1239 Char *n; 1240 Char *v; 1241 } dspmt[] = { 1242 { STRLANGEUCJP, STRKEUC }, 1243 { STRLANGEUCKR, STRKEUC }, 1244 { STRLANGEUCZH, STRKEUC }, 1245 { STRLANGEUCJPB, STRKEUC }, 1246 { STRLANGEUCKRB, STRKEUC }, 1247 { STRLANGEUCZHB, STRKEUC }, 1248#ifdef linux 1249 { STRLANGEUCJPC, STRKEUC }, 1250#endif 1251 { STRLANGSJIS, STRKSJIS }, 1252 { STRLANGSJISB, STRKSJIS }, 1253 { STRLANGBIG5, STRKBIG5 }, 1254 { STRSTARKUTF8, STRKUTF8 }, 1255 { NULL, NULL } 1256 }; 1257 1258 if (*pcp == '\0') 1259 return; 1260 1261 for (i = 0; dspmt[i].n; i++) { 1262 Char *estr; 1263 if (t_pmatch(pcp, dspmt[i].n, &estr, 1) > 0) { 1264 set(CHECK_MBYTEVAR, Strsave(dspmt[i].v), VAR_READWRITE); 1265 update_dspmbyte_vars(); 1266 break; 1267 } 1268 } 1269} 1270#endif 1271