/contrib/tcsh/sh.set.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1303 lines · 1091 code · 98 blank · 114 comment · 408 complexity · 2d11f72a8cf8761c5afa581bf1103e01 MD5 · raw file

  1. /* $Header: /p/tcsh/cvsroot/tcsh/sh.set.c,v 3.83 2012/01/15 17:15:28 christos Exp $ */
  2. /*
  3. * sh.set.c: Setting and Clearing of variables
  4. */
  5. /*-
  6. * Copyright (c) 1980, 1991 The Regents of the University of California.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #include "sh.h"
  34. RCSID("$tcsh: sh.set.c,v 3.83 2012/01/15 17:15:28 christos Exp $")
  35. #include "ed.h"
  36. #include "tw.h"
  37. #ifdef HAVE_NL_LANGINFO
  38. #include <langinfo.h>
  39. #endif
  40. extern int GotTermCaps;
  41. int numeof = 0;
  42. static void update_vars (Char *);
  43. static Char *getinx (Char *, int *);
  44. static void asx (Char *, int, Char *);
  45. static struct varent *getvx (Char *, int);
  46. static Char *xset (Char *, Char ***);
  47. static Char *operate (int, Char *, Char *);
  48. static void putn1 (tcsh_number_t);
  49. static struct varent *madrof (Char *, struct varent *);
  50. static void unsetv1 (struct varent *);
  51. static void exportpath (Char **);
  52. static void balance (struct varent *, int, int);
  53. /*
  54. * C Shell
  55. */
  56. static void
  57. update_vars(Char *vp)
  58. {
  59. if (eq(vp, STRpath)) {
  60. struct varent *p = adrof(STRpath);
  61. if (p == NULL)
  62. stderror(ERR_NAME | ERR_UNDVAR);
  63. else {
  64. exportpath(p->vec);
  65. dohash(NULL, NULL);
  66. }
  67. }
  68. else if (eq(vp, STRhistchars)) {
  69. Char *pn = varval(vp);
  70. HIST = *pn++;
  71. if (HIST)
  72. HISTSUB = *pn;
  73. else
  74. HISTSUB = HIST;
  75. }
  76. else if (eq(vp, STRpromptchars)) {
  77. Char *pn = varval(vp);
  78. PRCH = *pn++;
  79. if (PRCH)
  80. PRCHROOT = *pn;
  81. else
  82. PRCHROOT = PRCH;
  83. }
  84. else if (eq(vp, STRhistlit)) {
  85. HistLit = 1;
  86. }
  87. else if (eq(vp, STRuser)) {
  88. tsetenv(STRKUSER, varval(vp));
  89. tsetenv(STRLOGNAME, varval(vp));
  90. }
  91. else if (eq(vp, STRgroup)) {
  92. tsetenv(STRKGROUP, varval(vp));
  93. }
  94. else if (eq(vp, STRwordchars)) {
  95. word_chars = varval(vp);
  96. }
  97. else if (eq(vp, STRloginsh)) {
  98. loginsh = 1;
  99. }
  100. else if (eq(vp, STRanyerror)) {
  101. anyerror = 1;
  102. }
  103. else if (eq(vp, STRsymlinks)) {
  104. Char *pn = varval(vp);
  105. if (eq(pn, STRignore))
  106. symlinks = SYM_IGNORE;
  107. else if (eq(pn, STRexpand))
  108. symlinks = SYM_EXPAND;
  109. else if (eq(pn, STRchase))
  110. symlinks = SYM_CHASE;
  111. else
  112. symlinks = 0;
  113. }
  114. else if (eq(vp, STRterm)) {
  115. Char *cp = varval(vp);
  116. tsetenv(STRKTERM, cp);
  117. #ifdef DOESNT_WORK_RIGHT
  118. cp = getenv("TERMCAP");
  119. if (cp && (*cp != '/')) /* if TERMCAP and not a path */
  120. Unsetenv(STRTERMCAP);
  121. #endif /* DOESNT_WORK_RIGHT */
  122. GotTermCaps = 0;
  123. if (noediting && Strcmp(cp, STRnetwork) != 0 &&
  124. Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
  125. editing = 1;
  126. noediting = 0;
  127. setNS(STRedit);
  128. }
  129. ed_Init(); /* reset the editor */
  130. }
  131. else if (eq(vp, STRhome)) {
  132. Char *cp, *canon;
  133. cp = Strsave(varval(vp)); /* get the old value back */
  134. cleanup_push(cp, xfree);
  135. /*
  136. * convert to cononical pathname (possibly resolving symlinks)
  137. */
  138. canon = dcanon(cp, cp);
  139. cleanup_ignore(cp);
  140. cleanup_until(cp);
  141. cleanup_push(canon, xfree);
  142. setcopy(vp, canon, VAR_READWRITE); /* have to save the new val */
  143. /* and now mirror home with HOME */
  144. tsetenv(STRKHOME, canon);
  145. /* fix directory stack for new tilde home */
  146. dtilde();
  147. cleanup_until(canon);
  148. }
  149. else if (eq(vp, STRedit)) {
  150. editing = 1;
  151. noediting = 0;
  152. /* PWP: add more stuff in here later */
  153. }
  154. else if (eq(vp, STRshlvl)) {
  155. tsetenv(STRKSHLVL, varval(vp));
  156. }
  157. else if (eq(vp, STRignoreeof)) {
  158. Char *cp;
  159. numeof = 0;
  160. for ((cp = varval(STRignoreeof)); cp && *cp; cp++) {
  161. if (!Isdigit(*cp)) {
  162. numeof = 0;
  163. break;
  164. }
  165. numeof = numeof * 10 + *cp - '0';
  166. }
  167. if (numeof <= 0) numeof = 26; /* Sanity check */
  168. }
  169. else if (eq(vp, STRbackslash_quote)) {
  170. bslash_quote = 1;
  171. }
  172. else if (eq(vp, STRcompat_expr)) {
  173. compat_expr = 1;
  174. }
  175. else if (eq(vp, STRdirstack)) {
  176. dsetstack();
  177. }
  178. else if (eq(vp, STRrecognize_only_executables)) {
  179. tw_cmd_free();
  180. }
  181. else if (eq(vp, STRkillring)) {
  182. SetKillRing((int)getn(varval(vp)));
  183. }
  184. #ifndef HAVENOUTMP
  185. else if (eq(vp, STRwatch)) {
  186. resetwatch();
  187. }
  188. #endif /* HAVENOUTMP */
  189. else if (eq(vp, STRimplicitcd)) {
  190. implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
  191. }
  192. #ifdef COLOR_LS_F
  193. else if (eq(vp, STRcolor)) {
  194. set_color_context();
  195. }
  196. #endif /* COLOR_LS_F */
  197. #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
  198. else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
  199. update_dspmbyte_vars();
  200. }
  201. #endif
  202. #ifdef NLS_CATALOGS
  203. else if (eq(vp, STRcatalog)) {
  204. nlsclose();
  205. nlsinit();
  206. }
  207. #if defined(FILEC) && defined(TIOCSTI)
  208. else if (eq(vp, STRfilec))
  209. filec = 1;
  210. #endif
  211. #endif /* NLS_CATALOGS */
  212. }
  213. /*ARGSUSED*/
  214. void
  215. doset(Char **v, struct command *c)
  216. {
  217. Char *p;
  218. Char *vp;
  219. Char **vecp;
  220. int hadsub;
  221. int subscr;
  222. int flags = VAR_READWRITE;
  223. int first_match = 0;
  224. int last_match = 0;
  225. int changed = 0;
  226. USE(c);
  227. v++;
  228. do {
  229. changed = 0;
  230. /*
  231. * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov>
  232. */
  233. if (*v && eq(*v, STRmr)) {
  234. flags = VAR_READONLY;
  235. v++;
  236. changed = 1;
  237. }
  238. if (*v && eq(*v, STRmf) && !last_match) {
  239. first_match = 1;
  240. v++;
  241. changed = 1;
  242. }
  243. if (*v && eq(*v, STRml) && !first_match) {
  244. last_match = 1;
  245. v++;
  246. changed = 1;
  247. }
  248. } while(changed);
  249. p = *v++;
  250. if (p == 0) {
  251. plist(&shvhed, flags);
  252. return;
  253. }
  254. do {
  255. hadsub = 0;
  256. vp = p;
  257. if (!letter(*p))
  258. stderror(ERR_NAME | ERR_VARBEGIN);
  259. do {
  260. p++;
  261. } while (alnum(*p));
  262. if (*p == '[') {
  263. hadsub++;
  264. p = getinx(p, &subscr);
  265. }
  266. if (*p != '\0' && *p != '=')
  267. stderror(ERR_NAME | ERR_VARALNUM);
  268. if (*p == '=') {
  269. *p++ = '\0';
  270. if (*p == '\0' && *v != NULL && **v == '(')
  271. p = *v++;
  272. }
  273. else if (*v && eq(*v, STRequal)) {
  274. if (*++v != NULL)
  275. p = *v++;
  276. }
  277. if (eq(p, STRLparen)) {
  278. Char **e = v;
  279. if (hadsub)
  280. stderror(ERR_NAME | ERR_SYNTAX);
  281. for (;;) {
  282. if (!*e)
  283. stderror(ERR_NAME | ERR_MISSING, ')');
  284. if (**e == ')')
  285. break;
  286. e++;
  287. }
  288. p = *e;
  289. *e = 0;
  290. vecp = saveblk(v);
  291. if (first_match)
  292. flags |= VAR_FIRST;
  293. else if (last_match)
  294. flags |= VAR_LAST;
  295. set1(vp, vecp, &shvhed, flags);
  296. *e = p;
  297. v = e + 1;
  298. }
  299. else if (hadsub) {
  300. Char *copy;
  301. copy = Strsave(p);
  302. cleanup_push(copy, xfree);
  303. asx(vp, subscr, copy);
  304. cleanup_ignore(copy);
  305. cleanup_until(copy);
  306. }
  307. else
  308. setv(vp, Strsave(p), flags);
  309. update_vars(vp);
  310. } while ((p = *v++) != NULL);
  311. }
  312. static Char *
  313. getinx(Char *cp, 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. static void
  324. asx(Char *vp, int subscr, Char *p)
  325. {
  326. struct varent *v = getvx(vp, subscr);
  327. Char *prev;
  328. if (v->v_flags & VAR_READONLY)
  329. stderror(ERR_READONLY|ERR_NAME, v->v_name);
  330. prev = v->vec[subscr - 1];
  331. cleanup_push(prev, xfree);
  332. v->vec[subscr - 1] = globone(p, G_APPEND);
  333. cleanup_until(prev);
  334. }
  335. static struct varent *
  336. getvx(Char *vp, int subscr)
  337. {
  338. struct varent *v = adrof(vp);
  339. if (v == 0)
  340. udvar(vp);
  341. if (subscr < 1 || subscr > blklen(v->vec))
  342. stderror(ERR_NAME | ERR_RANGE);
  343. return (v);
  344. }
  345. /*ARGSUSED*/
  346. void
  347. dolet(Char **v, struct command *dummy)
  348. {
  349. Char *p;
  350. Char *vp, c, op;
  351. int hadsub;
  352. int subscr;
  353. USE(dummy);
  354. v++;
  355. p = *v++;
  356. if (p == 0) {
  357. prvars();
  358. return;
  359. }
  360. do {
  361. hadsub = 0;
  362. vp = p;
  363. if (letter(*p))
  364. for (; alnum(*p); p++)
  365. continue;
  366. if (vp == p || !letter(*vp))
  367. stderror(ERR_NAME | ERR_VARBEGIN);
  368. if (*p == '[') {
  369. hadsub++;
  370. p = getinx(p, &subscr);
  371. }
  372. if (*p == 0 && *v)
  373. p = *v++;
  374. if ((op = *p) != 0)
  375. *p++ = 0;
  376. else
  377. stderror(ERR_NAME | ERR_ASSIGN);
  378. /*
  379. * if there is no expression after the '=' then print a "Syntax Error"
  380. * message - strike
  381. */
  382. if (*p == '\0' && *v == NULL)
  383. stderror(ERR_NAME | ERR_ASSIGN);
  384. vp = Strsave(vp);
  385. cleanup_push(vp, xfree);
  386. if (op == '=') {
  387. c = '=';
  388. p = xset(p, &v);
  389. }
  390. else {
  391. c = *p++;
  392. if (any("+-", c)) {
  393. if (c != op || *p)
  394. stderror(ERR_NAME | ERR_UNKNOWNOP);
  395. p = Strsave(STR1);
  396. }
  397. else {
  398. if (any("<>", op)) {
  399. if (c != op)
  400. stderror(ERR_NAME | ERR_UNKNOWNOP);
  401. stderror(ERR_NAME | ERR_SYNTAX);
  402. }
  403. if (c != '=')
  404. stderror(ERR_NAME | ERR_UNKNOWNOP);
  405. p = xset(p, &v);
  406. }
  407. }
  408. cleanup_push(p, xfree);
  409. if (op == '=') {
  410. if (hadsub)
  411. asx(vp, subscr, p);
  412. else
  413. setv(vp, p, VAR_READWRITE);
  414. cleanup_ignore(p);
  415. }
  416. else if (hadsub) {
  417. struct varent *gv = getvx(vp, subscr);
  418. Char *val;
  419. val = operate(op, gv->vec[subscr - 1], p);
  420. cleanup_push(val, xfree);
  421. asx(vp, subscr, val);
  422. cleanup_ignore(val);
  423. cleanup_until(val);
  424. }
  425. else {
  426. Char *val;
  427. val = operate(op, varval(vp), p);
  428. cleanup_push(val, xfree);
  429. setv(vp, val, VAR_READWRITE);
  430. cleanup_ignore(val);
  431. cleanup_until(val);
  432. }
  433. update_vars(vp);
  434. cleanup_until(vp);
  435. } while ((p = *v++) != NULL);
  436. }
  437. static Char *
  438. xset(Char *cp, Char ***vp)
  439. {
  440. Char *dp;
  441. if (*cp) {
  442. dp = Strsave(cp);
  443. --(*vp);
  444. xfree(** vp);
  445. **vp = dp;
  446. }
  447. return (putn(expr(vp)));
  448. }
  449. static Char *
  450. operate(int op, Char *vp, Char *p)
  451. {
  452. Char opr[2];
  453. Char *vec[5];
  454. Char **v = vec;
  455. Char **vecp = v;
  456. tcsh_number_t i;
  457. if (op != '=') {
  458. if (*vp)
  459. *v++ = vp;
  460. opr[0] = op;
  461. opr[1] = 0;
  462. *v++ = opr;
  463. if (op == '<' || op == '>')
  464. *v++ = opr;
  465. }
  466. *v++ = p;
  467. *v++ = 0;
  468. i = expr(&vecp);
  469. if (*vecp)
  470. stderror(ERR_NAME | ERR_EXPRESSION);
  471. return (putn(i));
  472. }
  473. static Char *putp;
  474. Char *
  475. putn(tcsh_number_t n)
  476. {
  477. Char nbuf[1024]; /* Enough even for octal */
  478. putp = nbuf;
  479. if (n < 0) {
  480. n = -n;
  481. *putp++ = '-';
  482. }
  483. putn1(n);
  484. *putp = 0;
  485. return (Strsave(nbuf));
  486. }
  487. static void
  488. putn1(tcsh_number_t n)
  489. {
  490. if (n > 9)
  491. putn1(n / 10);
  492. *putp++ = (Char)(n % 10 + '0');
  493. }
  494. tcsh_number_t
  495. getn(const Char *cp)
  496. {
  497. tcsh_number_t n;
  498. int sign;
  499. int base;
  500. if (!cp) /* PWP: extra error checking */
  501. stderror(ERR_NAME | ERR_BADNUM);
  502. sign = 0;
  503. if (cp[0] == '+' && cp[1])
  504. cp++;
  505. if (*cp == '-') {
  506. sign++;
  507. cp++;
  508. if (!Isdigit(*cp))
  509. stderror(ERR_NAME | ERR_BADNUM);
  510. }
  511. if (cp[0] == '0' && cp[1] && is_set(STRparseoctal))
  512. base = 8;
  513. else
  514. base = 10;
  515. n = 0;
  516. while (Isdigit(*cp))
  517. {
  518. if (base == 8 && *cp >= '8')
  519. stderror(ERR_NAME | ERR_BADNUM);
  520. n = n * base + *cp++ - '0';
  521. }
  522. if (*cp)
  523. stderror(ERR_NAME | ERR_BADNUM);
  524. return (sign ? -n : n);
  525. }
  526. Char *
  527. value1(Char *var, struct varent *head)
  528. {
  529. struct varent *vp;
  530. if (!var || !head) /* PWP: extra error checking */
  531. return (STRNULL);
  532. vp = adrof1(var, head);
  533. return ((vp == NULL || vp->vec == NULL || vp->vec[0] == NULL) ?
  534. STRNULL : vp->vec[0]);
  535. }
  536. static struct varent *
  537. madrof(Char *pat, struct varent *vp)
  538. {
  539. struct varent *vp1;
  540. for (vp = vp->v_left; vp; vp = vp->v_right) {
  541. if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
  542. return vp1;
  543. if (Gmatch(vp->v_name, pat))
  544. return vp;
  545. }
  546. return vp;
  547. }
  548. struct varent *
  549. adrof1(const Char *name, struct varent *v)
  550. {
  551. int cmp;
  552. v = v->v_left;
  553. while (v && ((cmp = *name - *v->v_name) != 0 ||
  554. (cmp = Strcmp(name, v->v_name)) != 0))
  555. if (cmp < 0)
  556. v = v->v_left;
  557. else
  558. v = v->v_right;
  559. return v;
  560. }
  561. void
  562. setcopy(const Char *var, const Char *val, int flags)
  563. {
  564. Char *copy;
  565. copy = Strsave(val);
  566. cleanup_push(copy, xfree);
  567. setv(var, copy, flags);
  568. cleanup_ignore(copy);
  569. cleanup_until(copy);
  570. }
  571. /*
  572. * The caller is responsible for putting value in a safe place
  573. */
  574. void
  575. setv(const Char *var, Char *val, int flags)
  576. {
  577. Char **vec = xmalloc(2 * sizeof(Char **));
  578. vec[0] = val;
  579. vec[1] = 0;
  580. set1(var, vec, &shvhed, flags);
  581. }
  582. void
  583. set1(const Char *var, Char **vec, struct varent *head, int flags)
  584. {
  585. Char **oldv = vec;
  586. if ((flags & VAR_NOGLOB) == 0) {
  587. int gflag;
  588. gflag = tglob(oldv);
  589. if (gflag) {
  590. vec = globall(oldv, gflag);
  591. if (vec == 0) {
  592. blkfree(oldv);
  593. stderror(ERR_NAME | ERR_NOMATCH);
  594. }
  595. blkfree(oldv);
  596. }
  597. }
  598. /*
  599. * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com>
  600. */
  601. if ( flags & (VAR_FIRST | VAR_LAST) ) {
  602. /*
  603. * Code for -f (VAR_FIRST) and -l (VAR_LAST) options.
  604. * Method:
  605. * Delete all duplicate words leaving "holes" in the word array (vec).
  606. * Then remove the "holes", keeping the order of the words unchanged.
  607. */
  608. if (vec && vec[0] && vec[1]) { /* more than one word ? */
  609. int i, j;
  610. int num_items;
  611. for (num_items = 0; vec[num_items]; num_items++)
  612. continue;
  613. if (flags & VAR_FIRST) {
  614. /* delete duplications, keeping first occurance */
  615. for (i = 1; i < num_items; i++)
  616. for (j = 0; j < i; j++)
  617. /* If have earlier identical item, remove i'th item */
  618. if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
  619. xfree(vec[i]);
  620. vec[i] = NULL;
  621. break;
  622. }
  623. } else if (flags & VAR_LAST) {
  624. /* delete duplications, keeping last occurance */
  625. for (i = 0; i < num_items - 1; i++)
  626. for (j = i + 1; j < num_items; j++)
  627. /* If have later identical item, remove i'th item */
  628. if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
  629. /* remove identical item (the first) */
  630. xfree(vec[i]);
  631. vec[i] = NULL;
  632. }
  633. }
  634. /* Compress items - remove empty items */
  635. for (j = i = 0; i < num_items; i++)
  636. if (vec[i])
  637. vec[j++] = vec[i];
  638. /* NULL-fy remaining items */
  639. for (; j < num_items; j++)
  640. vec[j] = NULL;
  641. }
  642. /* don't let the attribute propagate */
  643. flags &= ~(VAR_FIRST|VAR_LAST);
  644. }
  645. setq(var, vec, head, flags);
  646. }
  647. void
  648. setq(const Char *name, Char **vec, struct varent *p, int flags)
  649. {
  650. struct varent *c;
  651. int f;
  652. f = 0; /* tree hangs off the header's left link */
  653. while ((c = p->v_link[f]) != 0) {
  654. if ((f = *name - *c->v_name) == 0 &&
  655. (f = Strcmp(name, c->v_name)) == 0) {
  656. if (c->v_flags & VAR_READONLY)
  657. stderror(ERR_READONLY|ERR_NAME, c->v_name);
  658. blkfree(c->vec);
  659. c->v_flags = flags;
  660. trim(c->vec = vec);
  661. return;
  662. }
  663. p = c;
  664. f = f > 0;
  665. }
  666. p->v_link[f] = c = xmalloc(sizeof(struct varent));
  667. c->v_name = Strsave(name);
  668. c->v_flags = flags;
  669. c->v_bal = 0;
  670. c->v_left = c->v_right = 0;
  671. c->v_parent = p;
  672. balance(p, f, 0);
  673. trim(c->vec = vec);
  674. }
  675. /*ARGSUSED*/
  676. void
  677. unset(Char **v, struct command *c)
  678. {
  679. int did_roe, did_edit;
  680. USE(c);
  681. did_roe = adrof(STRrecognize_only_executables) != NULL;
  682. did_edit = adrof(STRedit) != NULL;
  683. unset1(v, &shvhed);
  684. #if defined(FILEC) && defined(TIOCSTI)
  685. if (adrof(STRfilec) == 0)
  686. filec = 0;
  687. #endif /* FILEC && TIOCSTI */
  688. if (adrof(STRhistchars) == 0) {
  689. HIST = '!';
  690. HISTSUB = '^';
  691. }
  692. if (adrof(STRignoreeof) == 0)
  693. numeof = 0;
  694. if (adrof(STRpromptchars) == 0) {
  695. PRCH = tcsh ? '>' : '%';
  696. PRCHROOT = '#';
  697. }
  698. if (adrof(STRhistlit) == 0)
  699. HistLit = 0;
  700. if (adrof(STRloginsh) == 0)
  701. loginsh = 0;
  702. if (adrof(STRanyerror) == 0)
  703. anyerror = 0;
  704. if (adrof(STRwordchars) == 0)
  705. word_chars = STR_WORD_CHARS;
  706. if (adrof(STRedit) == 0)
  707. editing = 0;
  708. if (adrof(STRbackslash_quote) == 0)
  709. bslash_quote = 0;
  710. if (adrof(STRcompat_expr) == 0)
  711. compat_expr = 0;
  712. if (adrof(STRsymlinks) == 0)
  713. symlinks = 0;
  714. if (adrof(STRimplicitcd) == 0)
  715. implicit_cd = 0;
  716. if (adrof(STRkillring) == 0)
  717. SetKillRing(0);
  718. if (did_edit && noediting && adrof(STRedit) == 0)
  719. noediting = 0;
  720. if (did_roe && adrof(STRrecognize_only_executables) == 0)
  721. tw_cmd_free();
  722. #ifdef COLOR_LS_F
  723. if (adrof(STRcolor) == 0)
  724. set_color_context();
  725. #endif /* COLOR_LS_F */
  726. #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
  727. update_dspmbyte_vars();
  728. #endif
  729. #ifdef NLS_CATALOGS
  730. nlsclose();
  731. nlsinit();
  732. #endif /* NLS_CATALOGS */
  733. }
  734. void
  735. unset1(Char *v[], struct varent *head)
  736. {
  737. struct varent *vp;
  738. int cnt;
  739. while (*++v) {
  740. cnt = 0;
  741. while ((vp = madrof(*v, head)) != NULL)
  742. if (vp->v_flags & VAR_READONLY)
  743. stderror(ERR_READONLY|ERR_NAME, vp->v_name);
  744. else
  745. unsetv1(vp), cnt++;
  746. if (cnt == 0)
  747. setname(short2str(*v));
  748. }
  749. }
  750. void
  751. unsetv(Char *var)
  752. {
  753. struct varent *vp;
  754. if ((vp = adrof1(var, &shvhed)) == 0)
  755. udvar(var);
  756. unsetv1(vp);
  757. }
  758. static void
  759. unsetv1(struct varent *p)
  760. {
  761. struct varent *c, *pp;
  762. int f;
  763. /*
  764. * Free associated memory first to avoid complications.
  765. */
  766. blkfree(p->vec);
  767. xfree(p->v_name);
  768. /*
  769. * If p is missing one child, then we can move the other into where p is.
  770. * Otherwise, we find the predecessor of p, which is guaranteed to have no
  771. * right child, copy it into p, and move it's left child into it.
  772. */
  773. if (p->v_right == 0)
  774. c = p->v_left;
  775. else if (p->v_left == 0)
  776. c = p->v_right;
  777. else {
  778. for (c = p->v_left; c->v_right; c = c->v_right)
  779. continue;
  780. p->v_name = c->v_name;
  781. p->v_flags = c->v_flags;
  782. p->vec = c->vec;
  783. p = c;
  784. c = p->v_left;
  785. }
  786. /*
  787. * Move c into where p is.
  788. */
  789. pp = p->v_parent;
  790. f = pp->v_right == p;
  791. if ((pp->v_link[f] = c) != 0)
  792. c->v_parent = pp;
  793. /*
  794. * Free the deleted node, and rebalance.
  795. */
  796. xfree(p);
  797. balance(pp, f, 1);
  798. }
  799. /* Set variable name to NULL. */
  800. void
  801. setNS(const Char *varName)
  802. {
  803. setcopy(varName, STRNULL, VAR_READWRITE);
  804. }
  805. /*ARGSUSED*/
  806. void
  807. shift(Char **v, struct command *c)
  808. {
  809. struct varent *argv;
  810. Char *name;
  811. USE(c);
  812. v++;
  813. name = *v;
  814. if (name == 0)
  815. name = STRargv;
  816. else
  817. (void) strip(name);
  818. argv = adrof(name);
  819. if (argv == NULL || argv->vec == NULL)
  820. udvar(name);
  821. if (argv->vec[0] == 0)
  822. stderror(ERR_NAME | ERR_NOMORE);
  823. lshift(argv->vec, 1);
  824. update_vars(name);
  825. }
  826. static void
  827. exportpath(Char **val)
  828. {
  829. struct Strbuf buf = Strbuf_INIT;
  830. Char *exppath;
  831. if (val)
  832. while (*val) {
  833. Strbuf_append(&buf, *val++);
  834. if (*val == 0 || eq(*val, STRRparen))
  835. break;
  836. Strbuf_append1(&buf, PATHSEP);
  837. }
  838. exppath = Strbuf_finish(&buf);
  839. cleanup_push(exppath, xfree);
  840. tsetenv(STRKPATH, exppath);
  841. cleanup_until(exppath);
  842. }
  843. #ifndef lint
  844. /*
  845. * Lint thinks these have null effect
  846. */
  847. /* macros to do single rotations on node p */
  848. # define rright(p) (\
  849. t = (p)->v_left,\
  850. (t)->v_parent = (p)->v_parent,\
  851. (((p)->v_left = t->v_right) != NULL) ?\
  852. (t->v_right->v_parent = (p)) : 0,\
  853. (t->v_right = (p))->v_parent = t,\
  854. (p) = t)
  855. # define rleft(p) (\
  856. t = (p)->v_right,\
  857. ((t)->v_parent = (p)->v_parent,\
  858. ((p)->v_right = t->v_left) != NULL) ? \
  859. (t->v_left->v_parent = (p)) : 0,\
  860. (t->v_left = (p))->v_parent = t,\
  861. (p) = t)
  862. #else
  863. static struct varent *
  864. rleft(struct varent *p)
  865. {
  866. return (p);
  867. }
  868. static struct varent *
  869. rright(struct varent *p)
  870. {
  871. return (p);
  872. }
  873. #endif /* ! lint */
  874. /*
  875. * Rebalance a tree, starting at p and up.
  876. * F == 0 means we've come from p's left child.
  877. * D == 1 means we've just done a delete, otherwise an insert.
  878. */
  879. static void
  880. balance(struct varent *p, int f, int d)
  881. {
  882. struct varent *pp;
  883. #ifndef lint
  884. struct varent *t; /* used by the rotate macros */
  885. #endif /* !lint */
  886. int ff;
  887. #ifdef lint
  888. ff = 0; /* Sun's lint is dumb! */
  889. #endif
  890. /*
  891. * Ok, from here on, p is the node we're operating on; pp is it's parent; f
  892. * is the branch of p from which we have come; ff is the branch of pp which
  893. * is p.
  894. */
  895. for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
  896. ff = pp->v_right == p;
  897. if (f ^ d) { /* right heavy */
  898. switch (p->v_bal) {
  899. case -1: /* was left heavy */
  900. p->v_bal = 0;
  901. break;
  902. case 0: /* was balanced */
  903. p->v_bal = 1;
  904. break;
  905. case 1: /* was already right heavy */
  906. switch (p->v_right->v_bal) {
  907. case 1: /* single rotate */
  908. pp->v_link[ff] = rleft(p);
  909. p->v_left->v_bal = 0;
  910. p->v_bal = 0;
  911. break;
  912. case 0: /* single rotate */
  913. pp->v_link[ff] = rleft(p);
  914. p->v_left->v_bal = 1;
  915. p->v_bal = -1;
  916. break;
  917. case -1: /* double rotate */
  918. (void) rright(p->v_right);
  919. pp->v_link[ff] = rleft(p);
  920. p->v_left->v_bal =
  921. p->v_bal < 1 ? 0 : -1;
  922. p->v_right->v_bal =
  923. p->v_bal > -1 ? 0 : 1;
  924. p->v_bal = 0;
  925. break;
  926. default:
  927. break;
  928. }
  929. break;
  930. default:
  931. break;
  932. }
  933. }
  934. else { /* left heavy */
  935. switch (p->v_bal) {
  936. case 1: /* was right heavy */
  937. p->v_bal = 0;
  938. break;
  939. case 0: /* was balanced */
  940. p->v_bal = -1;
  941. break;
  942. case -1: /* was already left heavy */
  943. switch (p->v_left->v_bal) {
  944. case -1: /* single rotate */
  945. pp->v_link[ff] = rright(p);
  946. p->v_right->v_bal = 0;
  947. p->v_bal = 0;
  948. break;
  949. case 0: /* single rotate */
  950. pp->v_link[ff] = rright(p);
  951. p->v_right->v_bal = -1;
  952. p->v_bal = 1;
  953. break;
  954. case 1: /* double rotate */
  955. (void) rleft(p->v_left);
  956. pp->v_link[ff] = rright(p);
  957. p->v_left->v_bal =
  958. p->v_bal < 1 ? 0 : -1;
  959. p->v_right->v_bal =
  960. p->v_bal > -1 ? 0 : 1;
  961. p->v_bal = 0;
  962. break;
  963. default:
  964. break;
  965. }
  966. break;
  967. default:
  968. break;
  969. }
  970. }
  971. /*
  972. * If from insert, then we terminate when p is balanced. If from
  973. * delete, then we terminate when p is unbalanced.
  974. */
  975. if ((p->v_bal == 0) ^ d)
  976. break;
  977. }
  978. }
  979. void
  980. plist(struct varent *p, int what)
  981. {
  982. struct varent *c;
  983. int len;
  984. for (;;) {
  985. while (p->v_left)
  986. p = p->v_left;
  987. x:
  988. if (p->v_parent == 0) /* is it the header? */
  989. break;
  990. if ((p->v_flags & what) != 0) {
  991. if (setintr) {
  992. int old_pintr_disabled;
  993. pintr_push_enable(&old_pintr_disabled);
  994. cleanup_until(&old_pintr_disabled);
  995. }
  996. len = blklen(p->vec);
  997. xprintf("%S\t", p->v_name);
  998. if (len != 1)
  999. xputchar('(');
  1000. blkpr(p->vec);
  1001. if (len != 1)
  1002. xputchar(')');
  1003. xputchar('\n');
  1004. }
  1005. if (p->v_right) {
  1006. p = p->v_right;
  1007. continue;
  1008. }
  1009. do {
  1010. c = p;
  1011. p = p->v_parent;
  1012. } while (p->v_right == c);
  1013. goto x;
  1014. }
  1015. }
  1016. #if defined(KANJI)
  1017. # if defined(SHORT_STRINGS) && defined(DSPMBYTE)
  1018. extern int dspmbyte_ls;
  1019. void
  1020. update_dspmbyte_vars(void)
  1021. {
  1022. int lp, iskcode;
  1023. Char *dstr1;
  1024. struct varent *vp;
  1025. /* if variable "nokanji" is set, multi-byte display is disabled */
  1026. if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) {
  1027. _enable_mbdisp = 1;
  1028. dstr1 = vp->vec[0];
  1029. if(eq (dstr1, STRsjis))
  1030. iskcode = 1;
  1031. else if (eq(dstr1, STReuc))
  1032. iskcode = 2;
  1033. else if (eq(dstr1, STRbig5))
  1034. iskcode = 3;
  1035. else if (eq(dstr1, STRutf8))
  1036. iskcode = 4;
  1037. else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) {
  1038. iskcode = 0;
  1039. }
  1040. else {
  1041. xprintf(CGETS(18, 2,
  1042. "Warning: unknown multibyte display; using default(euc(JP))\n"));
  1043. iskcode = 2;
  1044. }
  1045. if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls))
  1046. dspmbyte_ls = 1;
  1047. else
  1048. dspmbyte_ls = 0;
  1049. for (lp = 0; lp < 256 && iskcode > 0; lp++) {
  1050. switch (iskcode) {
  1051. case 1:
  1052. /* Shift-JIS */
  1053. _cmap[lp] = _cmap_mbyte[lp];
  1054. _mbmap[lp] = _mbmap_sjis[lp];
  1055. break;
  1056. case 2:
  1057. /* 2 ... euc */
  1058. _cmap[lp] = _cmap_mbyte[lp];
  1059. _mbmap[lp] = _mbmap_euc[lp];
  1060. break;
  1061. case 3:
  1062. /* 3 ... big5 */
  1063. _cmap[lp] = _cmap_mbyte[lp];
  1064. _mbmap[lp] = _mbmap_big5[lp];
  1065. break;
  1066. case 4:
  1067. /* 4 ... utf8 */
  1068. _cmap[lp] = _cmap_mbyte[lp];
  1069. _mbmap[lp] = _mbmap_utf8[lp];
  1070. break;
  1071. default:
  1072. xprintf(CGETS(18, 3,
  1073. "Warning: unknown multibyte code %d; multibyte disabled\n"),
  1074. iskcode);
  1075. _cmap[lp] = _cmap_c[lp];
  1076. _mbmap[lp] = 0; /* Default map all 0 */
  1077. _enable_mbdisp = 0;
  1078. break;
  1079. }
  1080. }
  1081. if (iskcode == 0) {
  1082. /* check original table */
  1083. if (Strlen(dstr1) != 256) {
  1084. xprintf(CGETS(18, 4,
  1085. "Warning: Invalid multibyte table length (%d); multibyte disabled\n"),
  1086. Strlen(dstr1));
  1087. _enable_mbdisp = 0;
  1088. }
  1089. for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) {
  1090. if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) {
  1091. xprintf(CGETS(18, 4,
  1092. "Warning: bad multibyte code at offset +%d; multibyte diabled\n"),
  1093. lp);
  1094. _enable_mbdisp = 0;
  1095. break;
  1096. }
  1097. }
  1098. /* set original table */
  1099. for (lp = 0; lp < 256; lp++) {
  1100. if (_enable_mbdisp == 1) {
  1101. _cmap[lp] = _cmap_mbyte[lp];
  1102. _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f);
  1103. }
  1104. else {
  1105. _cmap[lp] = _cmap_c[lp];
  1106. _mbmap[lp] = 0; /* Default map all 0 */
  1107. }
  1108. }
  1109. }
  1110. }
  1111. else {
  1112. for (lp = 0; lp < 256; lp++) {
  1113. _cmap[lp] = _cmap_c[lp];
  1114. _mbmap[lp] = 0; /* Default map all 0 */
  1115. }
  1116. _enable_mbdisp = 0;
  1117. dspmbyte_ls = 0;
  1118. }
  1119. #ifdef MBYTEDEBUG /* Sorry, use for beta testing */
  1120. {
  1121. Char mbmapstr[300];
  1122. for (lp = 0; lp < 256; lp++)
  1123. mbmapstr[lp] = _mbmap[lp] + '0';
  1124. mbmapstr[lp] = 0;
  1125. setcopy(STRmbytemap, mbmapstr, VAR_READWRITE);
  1126. }
  1127. #endif /* MBYTEMAP */
  1128. }
  1129. /* dspkanji/dspmbyte autosetting */
  1130. /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
  1131. void
  1132. autoset_dspmbyte(const Char *pcp)
  1133. {
  1134. int i;
  1135. static const struct dspm_autoset_Table {
  1136. Char *n;
  1137. Char *v;
  1138. } dspmt[] = {
  1139. { STRLANGEUCJP, STReuc },
  1140. { STRLANGEUCKR, STReuc },
  1141. { STRLANGEUCZH, STReuc },
  1142. { STRLANGEUCJPB, STReuc },
  1143. { STRLANGEUCKRB, STReuc },
  1144. { STRLANGEUCZHB, STReuc },
  1145. #ifdef __linux__
  1146. { STRLANGEUCJPC, STReuc },
  1147. #endif
  1148. { STRLANGSJIS, STRsjis },
  1149. { STRLANGSJISB, STRsjis },
  1150. { STRLANGBIG5, STRbig5 },
  1151. { STRstarutfstar8, STRutf8 },
  1152. { NULL, NULL }
  1153. };
  1154. #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
  1155. static const struct dspm_autoset_Table dspmc[] = {
  1156. { STRstarutfstar8, STRutf8 },
  1157. { STReuc, STReuc },
  1158. { STRGB2312, STReuc },
  1159. { STRLANGBIG5, STRbig5 },
  1160. { NULL, NULL }
  1161. };
  1162. Char *codeset;
  1163. codeset = str2short(nl_langinfo(CODESET));
  1164. if (*codeset != '\0') {
  1165. for (i = 0; dspmc[i].n; i++) {
  1166. const Char *estr;
  1167. if (dspmc[i].n[0] && t_pmatch(pcp, dspmc[i].n, &estr, 0) > 0) {
  1168. setcopy(CHECK_MBYTEVAR, dspmc[i].v, VAR_READWRITE);
  1169. update_dspmbyte_vars();
  1170. return;
  1171. }
  1172. }
  1173. }
  1174. #endif
  1175. if (*pcp == '\0')
  1176. return;
  1177. for (i = 0; dspmt[i].n; i++) {
  1178. const Char *estr;
  1179. if (dspmt[i].n[0] && t_pmatch(pcp, dspmt[i].n, &estr, 0) > 0) {
  1180. setcopy(CHECK_MBYTEVAR, dspmt[i].v, VAR_READWRITE);
  1181. update_dspmbyte_vars();
  1182. break;
  1183. }
  1184. }
  1185. }
  1186. # elif defined(AUTOSET_KANJI)
  1187. void
  1188. autoset_kanji(void)
  1189. {
  1190. char *codeset = nl_langinfo(CODESET);
  1191. if (*codeset == '\0') {
  1192. if (adrof(STRnokanji) == NULL)
  1193. setNS(STRnokanji);
  1194. return;
  1195. }
  1196. if (strcasestr(codeset, "SHIFT_JIS") == (char*)0) {
  1197. if (adrof(STRnokanji) == NULL)
  1198. setNS(STRnokanji);
  1199. return;
  1200. }
  1201. if (adrof(STRnokanji) != NULL)
  1202. unsetv(STRnokanji);
  1203. }
  1204. #endif
  1205. #endif