PageRenderTime 59ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/tcsh/sh.func.c

https://bitbucket.org/freebsd/freebsd-head/
C | 2683 lines | 2196 code | 252 blank | 235 comment | 666 complexity | 9ce457f10143ce4bcd4667605e6b1e76 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  1. /* $Header: /p/tcsh/cvsroot/tcsh/sh.func.c,v 3.162 2011/02/26 00:07:06 christos Exp $ */
  2. /*
  3. * sh.func.c: csh builtin functions
  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.func.c,v 3.162 2011/02/26 00:07:06 christos Exp $")
  35. #include "ed.h"
  36. #include "tw.h"
  37. #include "tc.h"
  38. #ifdef WINNT_NATIVE
  39. #include "nt.const.h"
  40. #endif /* WINNT_NATIVE */
  41. #if defined (NLS_CATALOGS) && defined(HAVE_ICONV)
  42. static iconv_t catgets_iconv; /* Or (iconv_t)-1 */
  43. #endif
  44. /*
  45. * C shell
  46. */
  47. extern int MapsAreInited;
  48. extern int NLSMapsAreInited;
  49. extern int GotTermCaps;
  50. static int zlast = -1;
  51. static void islogin (void);
  52. static void preread (void);
  53. static void doagain (void);
  54. static const char *isrchx (int);
  55. static void search (int, int, Char *);
  56. static int getword (struct Strbuf *);
  57. static struct wordent *histgetword (struct wordent *);
  58. static void toend (void);
  59. static void xecho (int, Char **);
  60. static int islocale_var (Char *);
  61. static void wpfree (struct whyle *);
  62. const struct biltins *
  63. isbfunc(struct command *t)
  64. {
  65. Char *cp = t->t_dcom[0];
  66. const struct biltins *bp, *bp1, *bp2;
  67. static struct biltins label = {"", dozip, 0, 0};
  68. static struct biltins foregnd = {"%job", dofg1, 0, 0};
  69. static struct biltins backgnd = {"%job &", dobg1, 0, 0};
  70. /*
  71. * We never match a builtin that has quoted the first
  72. * character; this has been the traditional way to escape
  73. * builtin commands.
  74. */
  75. if (*cp & QUOTE)
  76. return NULL;
  77. if (*cp != ':' && lastchr(cp) == ':') {
  78. label.bname = short2str(cp);
  79. return (&label);
  80. }
  81. if (*cp == '%') {
  82. if (t->t_dflg & F_AMPERSAND) {
  83. t->t_dflg &= ~F_AMPERSAND;
  84. backgnd.bname = short2str(cp);
  85. return (&backgnd);
  86. }
  87. foregnd.bname = short2str(cp);
  88. return (&foregnd);
  89. }
  90. #ifdef WARP
  91. /*
  92. * This is a perhaps kludgy way to determine if the warp builtin is to be
  93. * acknowledged or not. If checkwarp() fails, then we are to assume that
  94. * the warp command is invalid, and carry on as we would handle any other
  95. * non-builtin command. -- JDK 2/4/88
  96. */
  97. if (eq(STRwarp, cp) && !checkwarp()) {
  98. return (0); /* this builtin disabled */
  99. }
  100. #endif /* WARP */
  101. /*
  102. * Binary search Bp1 is the beginning of the current search range. Bp2 is
  103. * one past the end.
  104. */
  105. for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {
  106. int i;
  107. bp = bp1 + ((bp2 - bp1) >> 1);
  108. if ((i = ((char) *cp) - *bp->bname) == 0 &&
  109. (i = StrQcmp(cp, str2short(bp->bname))) == 0)
  110. return bp;
  111. if (i < 0)
  112. bp2 = bp;
  113. else
  114. bp1 = bp + 1;
  115. }
  116. #ifdef WINNT_NATIVE
  117. return nt_check_additional_builtins(cp);
  118. #endif /*WINNT_NATIVE*/
  119. return (0);
  120. }
  121. void
  122. func(struct command *t, const struct biltins *bp)
  123. {
  124. int i;
  125. xechoit(t->t_dcom);
  126. setname(bp->bname);
  127. i = blklen(t->t_dcom) - 1;
  128. if (i < bp->minargs)
  129. stderror(ERR_NAME | ERR_TOOFEW);
  130. if (i > bp->maxargs)
  131. stderror(ERR_NAME | ERR_TOOMANY);
  132. (*bp->bfunct) (t->t_dcom, t);
  133. }
  134. /*ARGSUSED*/
  135. void
  136. doonintr(Char **v, struct command *c)
  137. {
  138. Char *cp;
  139. Char *vv = v[1];
  140. USE(c);
  141. if (parintr.sa_handler == SIG_IGN)
  142. return;
  143. if (setintr && intty)
  144. stderror(ERR_NAME | ERR_TERMINAL);
  145. cp = gointr;
  146. gointr = 0;
  147. xfree(cp);
  148. if (vv == 0) {
  149. if (setintr)
  150. sigset_interrupting(SIGINT, queue_pintr);
  151. else
  152. (void) signal(SIGINT, SIG_DFL);
  153. gointr = 0;
  154. }
  155. else if (eq((vv = strip(vv)), STRminus)) {
  156. (void) signal(SIGINT, SIG_IGN);
  157. gointr = Strsave(STRminus);
  158. }
  159. else {
  160. gointr = Strsave(vv);
  161. sigset_interrupting(SIGINT, queue_pintr);
  162. }
  163. }
  164. /*ARGSUSED*/
  165. void
  166. donohup(Char **v, struct command *c)
  167. {
  168. USE(c);
  169. USE(v);
  170. if (intty)
  171. stderror(ERR_NAME | ERR_TERMINAL);
  172. if (setintr == 0) {
  173. (void) signal(SIGHUP, SIG_IGN);
  174. phup_disabled = 1;
  175. #ifdef CC
  176. submit(getpid());
  177. #endif /* CC */
  178. }
  179. }
  180. /*ARGSUSED*/
  181. void
  182. dohup(Char **v, struct command *c)
  183. {
  184. USE(c);
  185. USE(v);
  186. if (intty)
  187. stderror(ERR_NAME | ERR_TERMINAL);
  188. if (setintr == 0)
  189. (void) signal(SIGHUP, SIG_DFL);
  190. }
  191. /*ARGSUSED*/
  192. void
  193. dozip(Char **v, struct command *c)
  194. {
  195. USE(c);
  196. USE(v);
  197. }
  198. /*ARGSUSED*/
  199. void
  200. dofiletest(Char **v, struct command *c)
  201. {
  202. Char **globbed, **fileptr, *ftest, *res;
  203. USE(c);
  204. if (*(ftest = *++v) != '-')
  205. stderror(ERR_NAME | ERR_FILEINQ);
  206. ++v;
  207. v = glob_all_or_error(v);
  208. globbed = v;
  209. cleanup_push(globbed, blk_cleanup);
  210. while (*(fileptr = v++) != '\0') {
  211. res = filetest(ftest, &fileptr, 0);
  212. cleanup_push(res, xfree);
  213. xprintf("%S", res);
  214. cleanup_until(res);
  215. if (*v)
  216. xprintf(" ");
  217. }
  218. xprintf("\n");
  219. cleanup_until(globbed);
  220. }
  221. void
  222. prvars(void)
  223. {
  224. plist(&shvhed, VAR_ALL);
  225. }
  226. /*ARGSUSED*/
  227. void
  228. doalias(Char **v, struct command *c)
  229. {
  230. struct varent *vp;
  231. Char *p;
  232. USE(c);
  233. v++;
  234. p = *v++;
  235. if (p == 0)
  236. plist(&aliases, VAR_ALL);
  237. else if (*v == 0) {
  238. vp = adrof1(strip(p), &aliases);
  239. if (vp && vp->vec)
  240. blkpr(vp->vec), xputchar('\n');
  241. }
  242. else {
  243. if (eq(p, STRalias) || eq(p, STRunalias)) {
  244. setname(short2str(p));
  245. stderror(ERR_NAME | ERR_DANGER);
  246. }
  247. set1(strip(p), saveblk(v), &aliases, VAR_READWRITE);
  248. tw_cmd_free();
  249. }
  250. }
  251. /*ARGSUSED*/
  252. void
  253. unalias(Char **v, struct command *c)
  254. {
  255. USE(c);
  256. unset1(v, &aliases);
  257. tw_cmd_free();
  258. }
  259. /*ARGSUSED*/
  260. void
  261. dologout(Char **v, struct command *c)
  262. {
  263. USE(c);
  264. USE(v);
  265. islogin();
  266. goodbye(NULL, NULL);
  267. }
  268. /*ARGSUSED*/
  269. void
  270. dologin(Char **v, struct command *c)
  271. {
  272. #ifdef WINNT_NATIVE
  273. USE(c);
  274. USE(v);
  275. #else /* !WINNT_NATIVE */
  276. char **p = short2blk(v);
  277. USE(c);
  278. cleanup_push((Char **)p, blk_cleanup);
  279. islogin();
  280. rechist(NULL, adrof(STRsavehist) != NULL);
  281. sigaction(SIGTERM, &parterm, NULL);
  282. (void) execv(_PATH_BIN_LOGIN, p);
  283. (void) execv(_PATH_USRBIN_LOGIN, p);
  284. cleanup_until((Char **)p);
  285. untty();
  286. xexit(1);
  287. #endif /* !WINNT_NATIVE */
  288. }
  289. #ifdef NEWGRP
  290. /*ARGSUSED*/
  291. void
  292. donewgrp(Char **v, struct command *c)
  293. {
  294. char **p;
  295. if (chkstop == 0 && setintr)
  296. panystop(0);
  297. sigaction(SIGTERM, &parterm, NULL);
  298. p = short2blk(v);
  299. /*
  300. * From Beto Appleton (beto@aixwiz.austin.ibm.com)
  301. * Newgrp can take 2 arguments...
  302. */
  303. (void) execv(_PATH_BIN_NEWGRP, p);
  304. (void) execv(_PATH_USRBIN_NEWGRP, p);
  305. blkfree((Char **) p);
  306. untty();
  307. xexit(1);
  308. }
  309. #endif /* NEWGRP */
  310. static void
  311. islogin(void)
  312. {
  313. if (chkstop == 0 && setintr)
  314. panystop(0);
  315. if (loginsh)
  316. return;
  317. stderror(ERR_NOTLOGIN);
  318. }
  319. void
  320. doif(Char **v, struct command *kp)
  321. {
  322. int i;
  323. Char **vv;
  324. v++;
  325. i = noexec ? 1 : expr(&v);
  326. vv = v;
  327. if (*vv == NULL)
  328. stderror(ERR_NAME | ERR_EMPTYIF);
  329. if (eq(*vv, STRthen)) {
  330. if (*++vv)
  331. stderror(ERR_NAME | ERR_IMPRTHEN);
  332. setname(short2str(STRthen));
  333. /*
  334. * If expression was zero, then scan to else , otherwise just fall into
  335. * following code.
  336. */
  337. if (!i)
  338. search(TC_IF, 0, NULL);
  339. return;
  340. }
  341. /*
  342. * Simple command attached to this if. Left shift the node in this tree,
  343. * munging it so we can reexecute it.
  344. */
  345. if (i) {
  346. lshift(kp->t_dcom, vv - kp->t_dcom);
  347. reexecute(kp);
  348. donefds();
  349. }
  350. }
  351. /*
  352. * Reexecute a command, being careful not
  353. * to redo i/o redirection, which is already set up.
  354. */
  355. void
  356. reexecute(struct command *kp)
  357. {
  358. kp->t_dflg &= F_SAVE;
  359. kp->t_dflg |= F_REPEAT;
  360. /*
  361. * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
  362. * pgrp's as the jobs would then have no way to get the tty (we can't give
  363. * it to them, and our parent wouldn't know their pgrp, etc.
  364. */
  365. execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL, TRUE);
  366. }
  367. /*ARGSUSED*/
  368. void
  369. doelse (Char **v, struct command *c)
  370. {
  371. USE(c);
  372. USE(v);
  373. if (!noexec)
  374. search(TC_ELSE, 0, NULL);
  375. }
  376. /*ARGSUSED*/
  377. void
  378. dogoto(Char **v, struct command *c)
  379. {
  380. Char *lp;
  381. USE(c);
  382. lp = globone(v[1], G_ERROR);
  383. cleanup_push(lp, xfree);
  384. if (!noexec)
  385. gotolab(lp);
  386. cleanup_until(lp);
  387. }
  388. void
  389. gotolab(Char *lab)
  390. {
  391. struct whyle *wp;
  392. /*
  393. * While we still can, locate any unknown ends of existing loops. This
  394. * obscure code is the WORST result of the fact that we don't really parse.
  395. */
  396. zlast = TC_GOTO;
  397. for (wp = whyles; wp; wp = wp->w_next)
  398. if (wp->w_end.type == TCSH_F_SEEK && wp->w_end.f_seek == 0) {
  399. search(TC_BREAK, 0, NULL);
  400. btell(&wp->w_end);
  401. }
  402. else {
  403. bseek(&wp->w_end);
  404. }
  405. search(TC_GOTO, 0, lab);
  406. /*
  407. * Eliminate loops which were exited.
  408. */
  409. wfree();
  410. }
  411. /*ARGSUSED*/
  412. void
  413. doswitch(Char **v, struct command *c)
  414. {
  415. Char *cp, *lp;
  416. USE(c);
  417. v++;
  418. if (!*v || *(*v++) != '(')
  419. stderror(ERR_SYNTAX);
  420. cp = **v == ')' ? STRNULL : *v++;
  421. if (*(*v++) != ')')
  422. v--;
  423. if (*v)
  424. stderror(ERR_SYNTAX);
  425. lp = globone(cp, G_ERROR);
  426. cleanup_push(lp, xfree);
  427. if (!noexec)
  428. search(TC_SWITCH, 0, lp);
  429. cleanup_until(lp);
  430. }
  431. /*ARGSUSED*/
  432. void
  433. dobreak(Char **v, struct command *c)
  434. {
  435. USE(v);
  436. USE(c);
  437. if (whyles == NULL)
  438. stderror(ERR_NAME | ERR_NOTWHILE);
  439. if (!noexec)
  440. toend();
  441. }
  442. /*ARGSUSED*/
  443. void
  444. doexit(Char **v, struct command *c)
  445. {
  446. USE(c);
  447. if (chkstop == 0 && (intty || intact) && evalvec == 0)
  448. panystop(0);
  449. /*
  450. * Don't DEMAND parentheses here either.
  451. */
  452. v++;
  453. if (*v) {
  454. setv(STRstatus, putn(expr(&v)), VAR_READWRITE);
  455. if (*v)
  456. stderror(ERR_NAME | ERR_EXPRESSION);
  457. }
  458. btoeof();
  459. #if 0
  460. if (intty)
  461. #endif
  462. /* Always close, why only on ttys? */
  463. xclose(SHIN);
  464. }
  465. /*ARGSUSED*/
  466. void
  467. doforeach(Char **v, struct command *c)
  468. {
  469. Char *cp, *sp;
  470. struct whyle *nwp;
  471. int gflag;
  472. USE(c);
  473. v++;
  474. cp = sp = strip(*v);
  475. if (!letter(*cp))
  476. stderror(ERR_NAME | ERR_VARBEGIN);
  477. do {
  478. cp++;
  479. } while (alnum(*cp));
  480. if (*cp != '\0')
  481. stderror(ERR_NAME | ERR_VARALNUM);
  482. cp = *v++;
  483. if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
  484. stderror(ERR_NAME | ERR_NOPAREN);
  485. v++;
  486. gflag = tglob(v);
  487. if (gflag) {
  488. v = globall(v, gflag);
  489. if (v == 0 && !noexec)
  490. stderror(ERR_NAME | ERR_NOMATCH);
  491. }
  492. else {
  493. v = saveblk(v);
  494. trim(v);
  495. }
  496. nwp = xcalloc(1, sizeof *nwp);
  497. nwp->w_fe = nwp->w_fe0 = v;
  498. btell(&nwp->w_start);
  499. nwp->w_fename = Strsave(cp);
  500. nwp->w_next = whyles;
  501. nwp->w_end.type = TCSH_F_SEEK;
  502. whyles = nwp;
  503. /*
  504. * Pre-read the loop so as to be more comprehensible to a terminal user.
  505. */
  506. zlast = TC_FOREACH;
  507. if (intty)
  508. preread();
  509. if (!noexec)
  510. doagain();
  511. }
  512. /*ARGSUSED*/
  513. void
  514. dowhile(Char **v, struct command *c)
  515. {
  516. int status;
  517. int again = whyles != 0 &&
  518. SEEKEQ(&whyles->w_start, &lineloc) &&
  519. whyles->w_fename == 0;
  520. USE(c);
  521. v++;
  522. /*
  523. * Implement prereading here also, taking care not to evaluate the
  524. * expression before the loop has been read up from a terminal.
  525. */
  526. if (noexec)
  527. status = 0;
  528. else if (intty && !again)
  529. status = !exp0(&v, 1);
  530. else
  531. status = !expr(&v);
  532. if (*v && !noexec)
  533. stderror(ERR_NAME | ERR_EXPRESSION);
  534. if (!again) {
  535. struct whyle *nwp = xcalloc(1, sizeof(*nwp));
  536. nwp->w_start = lineloc;
  537. nwp->w_end.type = TCSH_F_SEEK;
  538. nwp->w_end.f_seek = 0;
  539. nwp->w_end.a_seek = 0;
  540. nwp->w_next = whyles;
  541. whyles = nwp;
  542. zlast = TC_WHILE;
  543. if (intty) {
  544. /*
  545. * The tty preread
  546. */
  547. preread();
  548. doagain();
  549. return;
  550. }
  551. }
  552. if (status)
  553. /* We ain't gonna loop no more, no more! */
  554. toend();
  555. }
  556. static void
  557. preread(void)
  558. {
  559. int old_pintr_disabled;
  560. whyles->w_end.type = TCSH_I_SEEK;
  561. if (setintr)
  562. pintr_push_enable(&old_pintr_disabled);
  563. search(TC_BREAK, 0, NULL); /* read the expression in */
  564. if (setintr)
  565. cleanup_until(&old_pintr_disabled);
  566. btell(&whyles->w_end);
  567. }
  568. /*ARGSUSED*/
  569. void
  570. doend(Char **v, struct command *c)
  571. {
  572. USE(v);
  573. USE(c);
  574. if (!whyles)
  575. stderror(ERR_NAME | ERR_NOTWHILE);
  576. btell(&whyles->w_end);
  577. if (!noexec)
  578. doagain();
  579. }
  580. /*ARGSUSED*/
  581. void
  582. docontin(Char **v, struct command *c)
  583. {
  584. USE(v);
  585. USE(c);
  586. if (!whyles)
  587. stderror(ERR_NAME | ERR_NOTWHILE);
  588. if (!noexec)
  589. doagain();
  590. }
  591. static void
  592. doagain(void)
  593. {
  594. /* Repeating a while is simple */
  595. if (whyles->w_fename == 0) {
  596. bseek(&whyles->w_start);
  597. return;
  598. }
  599. /*
  600. * The foreach variable list actually has a spurious word ")" at the end of
  601. * the w_fe list. Thus we are at the of the list if one word beyond this
  602. * is 0.
  603. */
  604. if (!whyles->w_fe[1]) {
  605. dobreak(NULL, NULL);
  606. return;
  607. }
  608. setv(whyles->w_fename, quote(Strsave(*whyles->w_fe++)), VAR_READWRITE);
  609. bseek(&whyles->w_start);
  610. }
  611. void
  612. dorepeat(Char **v, struct command *kp)
  613. {
  614. int i = 1;
  615. do {
  616. i *= getn(v[1]);
  617. lshift(v, 2);
  618. } while (v[0] != NULL && Strcmp(v[0], STRrepeat) == 0);
  619. if (noexec)
  620. i = 1;
  621. if (setintr) {
  622. pintr_disabled++;
  623. cleanup_push(&pintr_disabled, disabled_cleanup);
  624. }
  625. while (i > 0) {
  626. if (setintr && pintr_disabled == 1) {
  627. cleanup_until(&pintr_disabled);
  628. pintr_disabled++;
  629. cleanup_push(&pintr_disabled, disabled_cleanup);
  630. }
  631. reexecute(kp);
  632. --i;
  633. }
  634. if (setintr && pintr_disabled == 1)
  635. cleanup_until(&pintr_disabled);
  636. donefds();
  637. }
  638. /*ARGSUSED*/
  639. void
  640. doswbrk(Char **v, struct command *c)
  641. {
  642. USE(v);
  643. USE(c);
  644. if (!noexec)
  645. search(TC_BRKSW, 0, NULL);
  646. }
  647. int
  648. srchx(Char *cp)
  649. {
  650. struct srch *sp, *sp1, *sp2;
  651. int i;
  652. /*
  653. * Ignore keywords inside heredocs
  654. */
  655. if (inheredoc)
  656. return -1;
  657. /*
  658. * Binary search Sp1 is the beginning of the current search range. Sp2 is
  659. * one past the end.
  660. */
  661. for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {
  662. sp = sp1 + ((sp2 - sp1) >> 1);
  663. if ((i = *cp - *sp->s_name) == 0 &&
  664. (i = Strcmp(cp, str2short(sp->s_name))) == 0)
  665. return sp->s_value;
  666. if (i < 0)
  667. sp2 = sp;
  668. else
  669. sp1 = sp + 1;
  670. }
  671. return (-1);
  672. }
  673. static const char *
  674. isrchx(int n)
  675. {
  676. struct srch *sp, *sp2;
  677. for (sp = srchn, sp2 = srchn + nsrchn; sp < sp2; sp++)
  678. if (sp->s_value == n)
  679. return (sp->s_name);
  680. return ("");
  681. }
  682. static int Stype;
  683. static Char *Sgoal;
  684. static void
  685. search(int type, int level, Char *goal)
  686. {
  687. struct Strbuf word = Strbuf_INIT;
  688. Char *cp;
  689. struct whyle *wp;
  690. int wlevel = 0;
  691. struct wordent *histent = NULL, *ohistent = NULL;
  692. Stype = type;
  693. Sgoal = goal;
  694. if (type == TC_GOTO) {
  695. struct Ain a;
  696. a.type = TCSH_F_SEEK;
  697. a.f_seek = 0;
  698. a.a_seek = 0;
  699. bseek(&a);
  700. }
  701. cleanup_push(&word, Strbuf_cleanup);
  702. do {
  703. if (intty) {
  704. histent = xmalloc(sizeof(*histent));
  705. ohistent = xmalloc(sizeof(*histent));
  706. ohistent->word = STRNULL;
  707. ohistent->next = histent;
  708. histent->prev = ohistent;
  709. }
  710. if (intty && fseekp == feobp && aret == TCSH_F_SEEK)
  711. printprompt(1, isrchx(type == TC_BREAK ? zlast : type));
  712. /* xprintf("? "), flush(); */
  713. (void) getword(&word);
  714. Strbuf_terminate(&word);
  715. if (intty && Strlen(word.s) > 0) {
  716. histent->word = Strsave(word.s);
  717. histent->next = xmalloc(sizeof(*histent));
  718. histent->next->prev = histent;
  719. histent = histent->next;
  720. }
  721. switch (srchx(word.s)) {
  722. case TC_ELSE:
  723. if (level == 0 && type == TC_IF)
  724. goto end;
  725. break;
  726. case TC_IF:
  727. while (getword(&word))
  728. continue;
  729. if ((type == TC_IF || type == TC_ELSE) &&
  730. eq(word.s, STRthen))
  731. level++;
  732. break;
  733. case TC_ENDIF:
  734. if (type == TC_IF || type == TC_ELSE)
  735. level--;
  736. break;
  737. case TC_FOREACH:
  738. case TC_WHILE:
  739. wlevel++;
  740. if (type == TC_BREAK)
  741. level++;
  742. break;
  743. case TC_END:
  744. if (type == TC_BRKSW) {
  745. if (wlevel == 0) {
  746. wp = whyles;
  747. if (wp) {
  748. whyles = wp->w_next;
  749. wpfree(wp);
  750. }
  751. }
  752. }
  753. if (type == TC_BREAK)
  754. level--;
  755. wlevel--;
  756. break;
  757. case TC_SWITCH:
  758. if (type == TC_SWITCH || type == TC_BRKSW)
  759. level++;
  760. break;
  761. case TC_ENDSW:
  762. if (type == TC_SWITCH || type == TC_BRKSW)
  763. level--;
  764. break;
  765. case TC_LABEL:
  766. if (type == TC_GOTO && getword(&word) && eq(word.s, goal))
  767. level = -1;
  768. break;
  769. default:
  770. if (type != TC_GOTO && (type != TC_SWITCH || level != 0))
  771. break;
  772. if (word.len == 0 || word.s[word.len - 1] != ':')
  773. break;
  774. word.s[--word.len] = 0;
  775. if ((type == TC_GOTO && eq(word.s, goal)) ||
  776. (type == TC_SWITCH && eq(word.s, STRdefault)))
  777. level = -1;
  778. break;
  779. case TC_CASE:
  780. if (type != TC_SWITCH || level != 0)
  781. break;
  782. (void) getword(&word);
  783. if (word.len != 0 && word.s[word.len - 1] == ':')
  784. word.s[--word.len] = 0;
  785. cp = strip(Dfix1(word.s));
  786. cleanup_push(cp, xfree);
  787. if (Gmatch(goal, cp))
  788. level = -1;
  789. cleanup_until(cp);
  790. break;
  791. case TC_DEFAULT:
  792. if (type == TC_SWITCH && level == 0)
  793. level = -1;
  794. break;
  795. }
  796. if (intty) {
  797. ohistent->prev = histgetword(histent);
  798. ohistent->prev->next = ohistent;
  799. savehist(ohistent, 0);
  800. freelex(ohistent);
  801. xfree(ohistent);
  802. } else
  803. (void) getword(NULL);
  804. } while (level >= 0);
  805. end:
  806. cleanup_until(&word);
  807. }
  808. static struct wordent *
  809. histgetword(struct wordent *histent)
  810. {
  811. int found = 0, first;
  812. eChar c, d;
  813. int e;
  814. struct Strbuf *tmp;
  815. tmp = xmalloc(sizeof(*tmp));
  816. tmp->size = 0;
  817. tmp->s = NULL;
  818. c = readc(1);
  819. d = 0;
  820. e = 0;
  821. for (;;) {
  822. tmp->len = 0;
  823. Strbuf_terminate (tmp);
  824. while (c == ' ' || c == '\t')
  825. c = readc(1);
  826. if (c == '#')
  827. do
  828. c = readc(1);
  829. while (c != CHAR_ERR && c != '\n');
  830. if (c == CHAR_ERR)
  831. goto past;
  832. if (c == '\n')
  833. goto nl;
  834. unreadc(c);
  835. found = 1;
  836. first = 1;
  837. do {
  838. e = (c == '\\');
  839. c = readc(1);
  840. if (c == '\\' && !e) {
  841. if ((c = readc(1)) == '\n') {
  842. e = 1;
  843. c = ' ';
  844. } else {
  845. unreadc(c);
  846. c = '\\';
  847. }
  848. }
  849. if ((c == '\'' || c == '"') && !e) {
  850. if (d == 0)
  851. d = c;
  852. else if (d == c)
  853. d = 0;
  854. }
  855. if (c == CHAR_ERR)
  856. goto past;
  857. Strbuf_append1(tmp, (Char) c);
  858. if (!first && !d && c == '(' && !e) {
  859. break;
  860. }
  861. first = 0;
  862. } while (d || e || (c != ' ' && c != '\t' && c != '\n'));
  863. tmp->len--;
  864. if (tmp->len) {
  865. Strbuf_terminate(tmp);
  866. histent->word = Strsave(tmp->s);
  867. histent->next = xmalloc(sizeof (*histent));
  868. histent->next->prev = histent;
  869. histent = histent->next;
  870. }
  871. if (c == '\n') {
  872. nl:
  873. tmp->len = 0;
  874. Strbuf_append1(tmp, (Char) c);
  875. Strbuf_terminate(tmp);
  876. histent->word = Strsave(tmp->s);
  877. return histent;
  878. }
  879. }
  880. past:
  881. switch (Stype) {
  882. case TC_IF:
  883. stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
  884. break;
  885. case TC_ELSE:
  886. stderror(ERR_NAME | ERR_NOTFOUND, "endif");
  887. break;
  888. case TC_BRKSW:
  889. case TC_SWITCH:
  890. stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
  891. break;
  892. case TC_BREAK:
  893. stderror(ERR_NAME | ERR_NOTFOUND, "end");
  894. break;
  895. case TC_GOTO:
  896. setname(short2str(Sgoal));
  897. stderror(ERR_NAME | ERR_NOTFOUND, "label");
  898. break;
  899. default:
  900. break;
  901. }
  902. /* NOTREACHED */
  903. return NULL;
  904. }
  905. static int
  906. getword(struct Strbuf *wp)
  907. {
  908. int found = 0, first;
  909. eChar c, d;
  910. if (wp)
  911. wp->len = 0;
  912. c = readc(1);
  913. d = 0;
  914. do {
  915. while (c == ' ' || c == '\t')
  916. c = readc(1);
  917. if (c == '#')
  918. do
  919. c = readc(1);
  920. while (c != CHAR_ERR && c != '\n');
  921. if (c == CHAR_ERR)
  922. goto past;
  923. if (c == '\n') {
  924. if (wp)
  925. break;
  926. return (0);
  927. }
  928. unreadc(c);
  929. found = 1;
  930. first = 1;
  931. do {
  932. c = readc(1);
  933. if (c == '\\' && (c = readc(1)) == '\n')
  934. c = ' ';
  935. if (c == '\'' || c == '"') {
  936. if (d == 0)
  937. d = c;
  938. else if (d == c)
  939. d = 0;
  940. }
  941. if (c == CHAR_ERR)
  942. goto past;
  943. if (wp)
  944. Strbuf_append1(wp, (Char) c);
  945. if (!first && !d && c == '(') {
  946. if (wp)
  947. goto past_word_end;
  948. else
  949. break;
  950. }
  951. first = 0;
  952. } while ((d || (c != ' ' && c != '\t')) && c != '\n');
  953. } while (wp == 0);
  954. past_word_end:
  955. unreadc(c);
  956. if (found) {
  957. wp->len--;
  958. Strbuf_terminate(wp);
  959. }
  960. return (found);
  961. past:
  962. switch (Stype) {
  963. case TC_IF:
  964. stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
  965. break;
  966. case TC_ELSE:
  967. stderror(ERR_NAME | ERR_NOTFOUND, "endif");
  968. break;
  969. case TC_BRKSW:
  970. case TC_SWITCH:
  971. stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
  972. break;
  973. case TC_BREAK:
  974. stderror(ERR_NAME | ERR_NOTFOUND, "end");
  975. break;
  976. case TC_GOTO:
  977. setname(short2str(Sgoal));
  978. stderror(ERR_NAME | ERR_NOTFOUND, "label");
  979. break;
  980. default:
  981. break;
  982. }
  983. /* NOTREACHED */
  984. return (0);
  985. }
  986. static void
  987. toend(void)
  988. {
  989. if (whyles->w_end.type == TCSH_F_SEEK && whyles->w_end.f_seek == 0) {
  990. search(TC_BREAK, 0, NULL);
  991. btell(&whyles->w_end);
  992. whyles->w_end.f_seek--;
  993. }
  994. else {
  995. bseek(&whyles->w_end);
  996. }
  997. wfree();
  998. }
  999. static void
  1000. wpfree(struct whyle *wp)
  1001. {
  1002. if (wp->w_fe0)
  1003. blkfree(wp->w_fe0);
  1004. xfree(wp->w_fename);
  1005. xfree(wp);
  1006. }
  1007. void
  1008. wfree(void)
  1009. {
  1010. struct Ain o;
  1011. struct whyle *nwp;
  1012. #ifdef lint
  1013. nwp = NULL; /* sun lint is dumb! */
  1014. #endif
  1015. #ifdef FDEBUG
  1016. static const char foo[] = "IAFE";
  1017. #endif /* FDEBUG */
  1018. btell(&o);
  1019. #ifdef FDEBUG
  1020. xprintf("o->type %c o->a_seek %d o->f_seek %d\n",
  1021. foo[o.type + 1], o.a_seek, o.f_seek);
  1022. #endif /* FDEBUG */
  1023. for (; whyles; whyles = nwp) {
  1024. struct whyle *wp = whyles;
  1025. nwp = wp->w_next;
  1026. #ifdef FDEBUG
  1027. xprintf("start->type %c start->a_seek %d start->f_seek %d\n",
  1028. foo[wp->w_start.type+1],
  1029. wp->w_start.a_seek, wp->w_start.f_seek);
  1030. xprintf("end->type %c end->a_seek %d end->f_seek %d\n",
  1031. foo[wp->w_end.type + 1], wp->w_end.a_seek, wp->w_end.f_seek);
  1032. #endif /* FDEBUG */
  1033. /*
  1034. * XXX: We free loops that have different seek types.
  1035. */
  1036. if (wp->w_end.type != TCSH_I_SEEK && wp->w_start.type == wp->w_end.type &&
  1037. wp->w_start.type == o.type) {
  1038. if (wp->w_end.type == TCSH_F_SEEK) {
  1039. if (o.f_seek >= wp->w_start.f_seek &&
  1040. (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek))
  1041. break;
  1042. }
  1043. else {
  1044. if (o.a_seek >= wp->w_start.a_seek &&
  1045. (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek))
  1046. break;
  1047. }
  1048. }
  1049. wpfree(wp);
  1050. }
  1051. }
  1052. /*ARGSUSED*/
  1053. void
  1054. doecho(Char **v, struct command *c)
  1055. {
  1056. USE(c);
  1057. xecho(' ', v);
  1058. }
  1059. /*ARGSUSED*/
  1060. void
  1061. doglob(Char **v, struct command *c)
  1062. {
  1063. USE(c);
  1064. xecho(0, v);
  1065. flush();
  1066. }
  1067. static void
  1068. xecho(int sep, Char **v)
  1069. {
  1070. Char *cp, **globbed = NULL;
  1071. int nonl = 0;
  1072. int echo_style = ECHO_STYLE;
  1073. struct varent *vp;
  1074. if ((vp = adrof(STRecho_style)) != NULL && vp->vec != NULL &&
  1075. vp->vec[0] != NULL) {
  1076. if (Strcmp(vp->vec[0], STRbsd) == 0)
  1077. echo_style = BSD_ECHO;
  1078. else if (Strcmp(vp->vec[0], STRsysv) == 0)
  1079. echo_style = SYSV_ECHO;
  1080. else if (Strcmp(vp->vec[0], STRboth) == 0)
  1081. echo_style = BOTH_ECHO;
  1082. else if (Strcmp(vp->vec[0], STRnone) == 0)
  1083. echo_style = NONE_ECHO;
  1084. }
  1085. v++;
  1086. if (*v == 0)
  1087. goto done;
  1088. if (setintr) {
  1089. int old_pintr_disabled;
  1090. pintr_push_enable(&old_pintr_disabled);
  1091. v = glob_all_or_error(v);
  1092. cleanup_until(&old_pintr_disabled);
  1093. } else {
  1094. v = glob_all_or_error(v);
  1095. }
  1096. globbed = v;
  1097. if (globbed != NULL)
  1098. cleanup_push(globbed, blk_cleanup);
  1099. if ((echo_style & BSD_ECHO) != 0 && sep == ' ' && *v && eq(*v, STRmn))
  1100. nonl++, v++;
  1101. while ((cp = *v++) != 0) {
  1102. Char c;
  1103. if (setintr) {
  1104. int old_pintr_disabled;
  1105. pintr_push_enable(&old_pintr_disabled);
  1106. cleanup_until(&old_pintr_disabled);
  1107. }
  1108. while ((c = *cp++) != 0) {
  1109. if ((echo_style & SYSV_ECHO) != 0 && c == '\\') {
  1110. switch (c = *cp++) {
  1111. case 'a':
  1112. c = '\a';
  1113. break;
  1114. case 'b':
  1115. c = '\b';
  1116. break;
  1117. case 'c':
  1118. nonl = 1;
  1119. goto done;
  1120. case 'e':
  1121. #if 0 /* Windows does not understand \e */
  1122. c = '\e';
  1123. #else
  1124. c = CTL_ESC('\033');
  1125. #endif
  1126. break;
  1127. case 'f':
  1128. c = '\f';
  1129. break;
  1130. case 'n':
  1131. c = '\n';
  1132. break;
  1133. case 'r':
  1134. c = '\r';
  1135. break;
  1136. case 't':
  1137. c = '\t';
  1138. break;
  1139. case 'v':
  1140. c = '\v';
  1141. break;
  1142. case '\\':
  1143. c = '\\';
  1144. break;
  1145. case '0':
  1146. c = 0;
  1147. if (*cp >= '0' && *cp < '8')
  1148. c = c * 8 + *cp++ - '0';
  1149. if (*cp >= '0' && *cp < '8')
  1150. c = c * 8 + *cp++ - '0';
  1151. if (*cp >= '0' && *cp < '8')
  1152. c = c * 8 + *cp++ - '0';
  1153. break;
  1154. case '\0':
  1155. c = '\\';
  1156. cp--;
  1157. break;
  1158. default:
  1159. xputchar('\\' | QUOTE);
  1160. break;
  1161. }
  1162. }
  1163. xputwchar(c | QUOTE);
  1164. }
  1165. if (*v)
  1166. xputchar(sep | QUOTE);
  1167. }
  1168. done:
  1169. if (sep && nonl == 0)
  1170. xputchar('\n');
  1171. else
  1172. flush();
  1173. if (globbed != NULL)
  1174. cleanup_until(globbed);
  1175. }
  1176. /* check whether an environment variable should invoke 'set_locale()' */
  1177. static int
  1178. islocale_var(Char *var)
  1179. {
  1180. static Char *locale_vars[] = {
  1181. STRLANG, STRLC_ALL, STRLC_CTYPE, STRLC_NUMERIC,
  1182. STRLC_TIME, STRLC_COLLATE, STRLC_MESSAGES, STRLC_MONETARY, 0
  1183. };
  1184. Char **v;
  1185. for (v = locale_vars; *v; ++v)
  1186. if (eq(var, *v))
  1187. return 1;
  1188. return 0;
  1189. }
  1190. static void
  1191. xlate_cr_cleanup(void *dummy)
  1192. {
  1193. USE(dummy);
  1194. xlate_cr = 0;
  1195. }
  1196. /*ARGSUSED*/
  1197. void
  1198. doprintenv(Char **v, struct command *c)
  1199. {
  1200. Char *e;
  1201. USE(c);
  1202. v++;
  1203. if (*v == 0) {
  1204. Char **ep;
  1205. xlate_cr = 1;
  1206. cleanup_push(&xlate_cr, xlate_cr_cleanup);
  1207. for (ep = STR_environ; *ep; ep++) {
  1208. if (setintr) {
  1209. int old_pintr_disabled;
  1210. pintr_push_enable(&old_pintr_disabled);
  1211. cleanup_until(&old_pintr_disabled);
  1212. }
  1213. xprintf("%S\n", *ep);
  1214. }
  1215. cleanup_until(&xlate_cr);
  1216. }
  1217. else if ((e = tgetenv(*v)) != NULL) {
  1218. int old_output_raw;
  1219. old_output_raw = output_raw;
  1220. output_raw = 1;
  1221. cleanup_push(&old_output_raw, output_raw_restore);
  1222. xprintf("%S\n", e);
  1223. cleanup_until(&old_output_raw);
  1224. }
  1225. else
  1226. setcopy(STRstatus, STR1, VAR_READWRITE);
  1227. }
  1228. /* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things
  1229. (and anything else with a modern compiler) */
  1230. /*ARGSUSED*/
  1231. void
  1232. dosetenv(Char **v, struct command *c)
  1233. {
  1234. Char *vp, *lp;
  1235. USE(c);
  1236. if (*++v == 0) {
  1237. doprintenv(--v, 0);
  1238. return;
  1239. }
  1240. vp = *v++;
  1241. lp = vp;
  1242. if (!letter(*lp))
  1243. stderror(ERR_NAME | ERR_VARBEGIN);
  1244. do {
  1245. lp++;
  1246. } while (alnum(*lp));
  1247. if (*lp != '\0')
  1248. stderror(ERR_NAME | ERR_VARALNUM);
  1249. if ((lp = *v++) == 0)
  1250. lp = STRNULL;
  1251. lp = globone(lp, G_APPEND);
  1252. cleanup_push(lp, xfree);
  1253. tsetenv(vp, lp);
  1254. if (eq(vp, STRKPATH)) {
  1255. importpath(lp);
  1256. dohash(NULL, NULL);
  1257. cleanup_until(lp);
  1258. return;
  1259. }
  1260. #ifdef apollo
  1261. if (eq(vp, STRSYSTYPE)) {
  1262. dohash(NULL, NULL);
  1263. cleanup_until(lp);
  1264. return;
  1265. }
  1266. #endif /* apollo */
  1267. /* dspkanji/dspmbyte autosetting */
  1268. /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
  1269. #if defined(DSPMBYTE)
  1270. if(eq(vp, STRLANG) && !adrof(CHECK_MBYTEVAR)) {
  1271. autoset_dspmbyte(lp);
  1272. }
  1273. #endif
  1274. if (islocale_var(vp)) {
  1275. #ifdef NLS
  1276. int k;
  1277. # ifdef SETLOCALEBUG
  1278. dont_free = 1;
  1279. # endif /* SETLOCALEBUG */
  1280. (void) setlocale(LC_ALL, "");
  1281. # ifdef LC_COLLATE
  1282. (void) setlocale(LC_COLLATE, "");
  1283. # endif
  1284. # ifdef LC_CTYPE
  1285. (void) setlocale(LC_CTYPE, ""); /* for iscntrl */
  1286. # endif /* LC_CTYPE */
  1287. # if defined(AUTOSET_KANJI)
  1288. autoset_kanji();
  1289. # endif /* AUTOSET_KANJI */
  1290. # ifdef NLS_CATALOGS
  1291. # ifdef LC_MESSAGES
  1292. (void) setlocale(LC_MESSAGES, "");
  1293. # endif /* LC_MESSAGES */
  1294. nlsclose();
  1295. nlsinit();
  1296. # endif /* NLS_CATALOGS */
  1297. # ifdef SETLOCALEBUG
  1298. dont_free = 0;
  1299. # endif /* SETLOCALEBUG */
  1300. # ifdef STRCOLLBUG
  1301. fix_strcoll_bug();
  1302. # endif /* STRCOLLBUG */
  1303. tw_cmd_free(); /* since the collation sequence has changed */
  1304. for (k = 0200; k <= 0377 && !Isprint(CTL_ESC(k)); k++)
  1305. continue;
  1306. AsciiOnly = MB_CUR_MAX == 1 && k > 0377;
  1307. #else /* !NLS */
  1308. AsciiOnly = 0;
  1309. #endif /* NLS */
  1310. NLSMapsAreInited = 0;
  1311. ed_Init();
  1312. if (MapsAreInited && !NLSMapsAreInited)
  1313. ed_InitNLSMaps();
  1314. cleanup_until(lp);
  1315. return;
  1316. }
  1317. #ifdef NLS_CATALOGS
  1318. if (eq(vp, STRNLSPATH)) {
  1319. nlsclose();
  1320. nlsinit();
  1321. }
  1322. #endif
  1323. if (eq(vp, STRNOREBIND)) {
  1324. NoNLSRebind = 1;
  1325. MapsAreInited = 0;
  1326. NLSMapsAreInited = 0;
  1327. ed_InitMaps();
  1328. cleanup_until(lp);
  1329. return;
  1330. }
  1331. #ifdef WINNT_NATIVE
  1332. if (eq(vp, STRtcshlang)) {
  1333. nlsinit();
  1334. cleanup_until(lp);
  1335. return;
  1336. }
  1337. #endif /* WINNT_NATIVE */
  1338. if (eq(vp, STRKTERM)) {
  1339. char *t;
  1340. setv(STRterm, quote(lp), VAR_READWRITE); /* lp memory used here */
  1341. cleanup_ignore(lp);
  1342. cleanup_until(lp);
  1343. t = short2str(lp);
  1344. if (noediting && strcmp(t, "unknown") != 0 && strcmp(t,"dumb") != 0) {
  1345. editing = 1;
  1346. noediting = 0;
  1347. setNS(STRedit);
  1348. }
  1349. GotTermCaps = 0;
  1350. ed_Init();
  1351. return;
  1352. }
  1353. if (eq(vp, STRKHOME)) {
  1354. Char *canon;
  1355. /*
  1356. * convert to canonical pathname (possibly resolving symlinks)
  1357. */
  1358. canon = dcanon(lp, lp);
  1359. cleanup_ignore(lp);
  1360. cleanup_until(lp);
  1361. cleanup_push(canon, xfree);
  1362. setv(STRhome, quote(canon), VAR_READWRITE); /* lp memory used here */
  1363. cleanup_ignore(canon);
  1364. cleanup_until(canon);
  1365. /* fix directory stack for new tilde home */
  1366. dtilde();
  1367. return;
  1368. }
  1369. if (eq(vp, STRKSHLVL)) {
  1370. setv(STRshlvl, quote(lp), VAR_READWRITE); /* lp memory used here */
  1371. cleanup_ignore(lp);
  1372. cleanup_until(lp);
  1373. return;
  1374. }
  1375. if (eq(vp, STRKUSER)) {
  1376. setv(STRuser, quote(lp), VAR_READWRITE); /* lp memory used here */
  1377. cleanup_ignore(lp);
  1378. cleanup_until(lp);
  1379. return;
  1380. }
  1381. if (eq(vp, STRKGROUP)) {
  1382. setv(STRgroup, quote(lp), VAR_READWRITE); /* lp memory used here */
  1383. cleanup_ignore(lp);
  1384. cleanup_until(lp);
  1385. return;
  1386. }
  1387. #ifdef COLOR_LS_F
  1388. if (eq(vp, STRLS_COLORS)) {
  1389. parseLS_COLORS(lp);
  1390. cleanup_until(lp);
  1391. return;
  1392. }
  1393. #endif /* COLOR_LS_F */
  1394. #ifdef SIG_WINDOW
  1395. /*
  1396. * Load/Update $LINES $COLUMNS
  1397. */
  1398. if ((eq(lp, STRNULL) && (eq(vp, STRLINES) || eq(vp, STRCOLUMNS))) ||
  1399. eq(vp, STRTERMCAP)) {
  1400. cleanup_until(lp);
  1401. check_window_size(1);
  1402. return;
  1403. }
  1404. /*
  1405. * Change the size to the one directed by $LINES and $COLUMNS
  1406. */
  1407. if (eq(vp, STRLINES) || eq(vp, STRCOLUMNS)) {
  1408. #if 0
  1409. GotTermCaps = 0;
  1410. #endif
  1411. cleanup_until(lp);
  1412. ed_Init();
  1413. return;
  1414. }
  1415. #endif /* SIG_WINDOW */
  1416. cleanup_until(lp);
  1417. }
  1418. /*ARGSUSED*/
  1419. void
  1420. dounsetenv(Char **v, struct command *c)
  1421. {
  1422. Char **ep, *p, *n, *name;
  1423. int i, maxi;
  1424. USE(c);
  1425. /*
  1426. * Find the longest environment variable
  1427. */
  1428. for (maxi = 0, ep = STR_environ; *ep; ep++) {
  1429. for (i = 0, p = *ep; *p && *p != '='; p++, i++)
  1430. continue;
  1431. if (i > maxi)
  1432. maxi = i;
  1433. }
  1434. name = xmalloc((maxi + 1) * sizeof(Char));
  1435. cleanup_push(name, xfree);
  1436. while (++v && *v)
  1437. for (maxi = 1; maxi;)
  1438. for (maxi = 0, ep = STR_environ; *ep; ep++) {
  1439. for (n = name, p = *ep; *p && *p != '='; *n++ = *p++)
  1440. continue;
  1441. *n = '\0';
  1442. if (!Gmatch(name, *v))
  1443. continue;
  1444. maxi = 1;
  1445. /* Unset the name. This wasn't being done until
  1446. * later but most of the stuff following won't
  1447. * work (particularly the setlocale() and getenv()
  1448. * stuff) as intended until the name is actually
  1449. * removed. (sg)
  1450. */
  1451. Unsetenv(name);
  1452. if (eq(name, STRNOREBIND)) {
  1453. NoNLSRebind = 0;
  1454. MapsAreInited = 0;
  1455. NLSMapsAreInited = 0;
  1456. ed_InitMaps();
  1457. }
  1458. #ifdef apollo
  1459. else if (eq(name, STRSYSTYPE))
  1460. dohash(NULL, NULL);
  1461. #endif /* apollo */
  1462. else if (islocale_var(name)) {
  1463. #ifdef NLS
  1464. int k;
  1465. # ifdef SETLOCALEBUG
  1466. dont_free = 1;
  1467. # endif /* SETLOCALEBUG */
  1468. (void) setlocale(LC_ALL, "");
  1469. # ifdef LC_COLLATE
  1470. (void) setlocale(LC_COLLATE, "");
  1471. # endif
  1472. # ifdef LC_CTYPE
  1473. (void) setlocale(LC_CTYPE, ""); /* for iscntrl */
  1474. # endif /* LC_CTYPE */
  1475. # ifdef NLS_CATALOGS
  1476. # ifdef LC_MESSAGES
  1477. (void) setlocale(LC_MESSAGES, "");
  1478. # endif /* LC_MESSAGES */
  1479. nlsclose();
  1480. nlsinit();
  1481. # endif /* NLS_CATALOGS */
  1482. # ifdef SETLOCALEBUG
  1483. dont_free = 0;
  1484. # endif /* SETLOCALEBUG */
  1485. # ifdef STRCOLLBUG
  1486. fix_strcoll_bug();
  1487. # endif /* STRCOLLBUG */
  1488. tw_cmd_free();/* since the collation sequence has changed */
  1489. for (k = 0200; k <= 0377 && !Isprint(CTL_ESC(k)); k++)
  1490. continue;
  1491. AsciiOnly = MB_CUR_MAX == 1 && k > 0377;
  1492. #else /* !NLS */
  1493. AsciiOnly = getenv("LANG") == NULL &&
  1494. getenv("LC_CTYPE") == NULL;
  1495. #endif /* NLS */
  1496. NLSMapsAreInited = 0;
  1497. ed_Init();
  1498. if (MapsAreInited && !NLSMapsAreInited)
  1499. ed_InitNLSMaps();
  1500. }
  1501. #ifdef WINNT_NATIVE
  1502. else if (eq(name,(STRtcshlang))) {
  1503. nls_dll_unload();
  1504. nlsinit();
  1505. }
  1506. #endif /* WINNT_NATIVE */
  1507. #ifdef COLOR_LS_F
  1508. else if (eq(name, STRLS_COLORS))
  1509. parseLS_COLORS(n);
  1510. #endif /* COLOR_LS_F */
  1511. #ifdef NLS_CATALOGS
  1512. else if (eq(name, STRNLSPATH)) {
  1513. nlsclose();
  1514. nlsinit();
  1515. }
  1516. #endif
  1517. /*
  1518. * start again cause the environment changes
  1519. */
  1520. break;
  1521. }
  1522. cleanup_until(name);
  1523. }
  1524. void
  1525. tsetenv(const Char *name, const Char *val)
  1526. {
  1527. #ifdef SETENV_IN_LIB
  1528. /*
  1529. * XXX: This does not work right, since tcsh cannot track changes to
  1530. * the environment this way. (the builtin setenv without arguments does
  1531. * not print the right stuff neither does unsetenv). This was for Mach,
  1532. * it is not needed anymore.
  1533. */
  1534. #undef setenv
  1535. char *cname;
  1536. if (name == NULL)
  1537. return;
  1538. cname = strsave(short2str(name));
  1539. setenv(cname, short2str(val), 1);
  1540. xfree(cname);
  1541. #else /* !SETENV_IN_LIB */
  1542. Char **ep = STR_environ;
  1543. const Char *ccp;
  1544. Char *cp, *dp;
  1545. Char *blk[2];
  1546. Char **oep = ep;
  1547. #ifdef WINNT_NATIVE
  1548. nt_set_env(name,val);
  1549. #endif /* WINNT_NATIVE */
  1550. for (; *ep; ep++) {
  1551. #ifdef WINNT_NATIVE
  1552. for (ccp = name, dp = *ep; *ccp && Tolower(*ccp & TRIM) == Tolower(*dp);
  1553. ccp++, dp++)
  1554. #else
  1555. for (ccp = name, dp = *ep; *ccp && (*ccp & TRIM) == *dp; ccp++, dp++)
  1556. #endif /* WINNT_NATIVE */
  1557. continue;
  1558. if (*ccp != 0 || *dp != '=')
  1559. continue;
  1560. cp = Strspl(STRequal, val);
  1561. xfree(*ep);
  1562. *ep = strip(Strspl(name, cp));
  1563. xfree(cp);
  1564. blkfree((Char **) environ);
  1565. environ = short2blk(STR_environ);
  1566. return;
  1567. }
  1568. cp = Strspl(name, STRequal);
  1569. blk[0] = strip(Strspl(cp, val));
  1570. xfree(cp);
  1571. blk[1] = 0;
  1572. STR_environ = blkspl(STR_environ, blk);
  1573. blkfree((Char **) environ);
  1574. environ = short2blk(STR_environ);
  1575. xfree(oep);
  1576. #endif /* SETENV_IN_LIB */
  1577. }
  1578. void
  1579. Unsetenv(Char *name)
  1580. {
  1581. Char **ep = STR_environ;
  1582. Char *cp, *dp;
  1583. Char **oep = ep;
  1584. #ifdef WINNT_NATIVE
  1585. nt_set_env(name,NULL);
  1586. #endif /*WINNT_NATIVE */
  1587. for (; *ep; ep++) {
  1588. for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
  1589. continue;
  1590. if (*cp != 0 || *dp != '=')
  1591. continue;
  1592. cp = *ep;
  1593. *ep = 0;
  1594. STR_environ = blkspl(STR_environ, ep + 1);
  1595. blkfree((Char **) environ);
  1596. environ = short2blk(STR_environ);
  1597. *ep = cp;
  1598. xfree(cp);
  1599. xfree(oep);
  1600. return;
  1601. }
  1602. }
  1603. /*ARGSUSED*/
  1604. void
  1605. doumask(Char **v, struct command *c)
  1606. {
  1607. Char *cp = v[1];
  1608. int i;
  1609. USE(c);
  1610. if (cp == 0) {
  1611. i = (int)umask(0);
  1612. (void) umask(i);
  1613. xprintf("%o\n", i);
  1614. return;
  1615. }
  1616. i = 0;
  1617. while (Isdigit(*cp) && *cp != '8' && *cp != '9')
  1618. i = i * 8 + *cp++ - '0';
  1619. if (*cp || i < 0 || i > 0777)
  1620. stderror(ERR_NAME | ERR_MASK);
  1621. (void) umask(i);
  1622. }
  1623. #ifndef HAVENOLIMIT
  1624. # ifndef BSDLIMIT
  1625. typedef long RLIM_TYPE;
  1626. # ifdef _OSD_POSIX /* BS2000 */
  1627. # include <ulimit.h>
  1628. # endif
  1629. # ifndef RLIM_INFINITY
  1630. # if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY)
  1631. extern RLIM_TYPE ulimit();
  1632. # endif /* ! _MINIX && !__clipper__ */
  1633. # define RLIM_INFINITY 0x003fffff
  1634. # define RLIMIT_FSIZE 1
  1635. # endif /* RLIM_INFINITY */
  1636. # ifdef aiws
  1637. # define toset(a) (((a) == 3) ? 1004 : (a) + 1)
  1638. # define RLIMIT_DATA 3
  1639. # define RLIMIT_STACK 1005
  1640. # else /* aiws */
  1641. # define toset(a) ((a) + 1)
  1642. # endif /* aiws */
  1643. # else /* BSDLIMIT */
  1644. # if (defined(BSD4_4) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || (HPUXVERSION >= 1100)) && !defined(__386BSD__)
  1645. typedef rlim_t RLIM_TYPE;
  1646. # else
  1647. # if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3)
  1648. typedef rlim_t RLIM_TYPE;
  1649. # else
  1650. # if defined(_SX)
  1651. typedef long long RLIM_TYPE;
  1652. # else /* !_SX */
  1653. typedef unsigned long RLIM_TYPE;
  1654. # endif /* _SX */
  1655. # endif /* SOLARIS2 || (sgi && SYSVREL > 3) */
  1656. # endif /* BSD4_4 && !__386BSD__ */
  1657. # endif /* BSDLIMIT */
  1658. # if (HPUXVERSION > 700) && (HPUXVERSION < 1100) && defined(BSDLIMIT)
  1659. /* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */
  1660. /* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */
  1661. # ifndef RLIMIT_CPU
  1662. # define RLIMIT_CPU 0
  1663. # define RLIMIT_FSIZE 1
  1664. # define RLIMIT_DATA 2
  1665. # define RLIMIT_STACK 3
  1666. # define RLIMIT_CORE 4
  1667. # define RLIMIT_RSS 5
  1668. # define RLIMIT_NOFILE 6
  1669. # endif /* RLIMIT_CPU */
  1670. # ifndef RLIM_INFINITY
  1671. # define RLIM_INFINITY 0x7fffffff
  1672. # endif /* RLIM_INFINITY */
  1673. /*
  1674. * old versions of HP/UX counted limits in 512 bytes
  1675. */
  1676. # ifndef SIGRTMIN
  1677. # define FILESIZE512
  1678. # endif /* SIGRTMIN */
  1679. # endif /* (HPUXVERSION > 700) && (HPUXVERSION < 1100) && BSDLIMIT */
  1680. # if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX)
  1681. /* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */
  1682. /* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */
  1683. /* than include both and get warnings, we define the extra SVR4 limits here. */
  1684. /* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */
  1685. /* RLIMIT_VMEM based on it? */
  1686. # ifndef RLIMIT_VMEM
  1687. # define RLIMIT_VMEM 6
  1688. # endif
  1689. # ifndef RLIMIT_AS
  1690. # define RLIMIT_AS RLIMIT_VMEM
  1691. # endif
  1692. # endif /* SYSVREL > 3 && BSDLIMIT */
  1693. # if (defined(__linux__) || defined(__GNU__) || defined(__GLIBC__))
  1694. # if defined(RLIMIT_AS) && !defined(RLIMIT_VMEM)
  1695. # define RLIMIT_VMEM RLIMIT_AS
  1696. # endif
  1697. /*
  1698. * Oh well, <asm-generic/resource.h> has it, but <bits/resource.h> does not
  1699. * Linux headers: When the left hand does not know what the right hand does.
  1700. */
  1701. # if defined(RLIMIT_RTPRIO) && !defined(RLIMIT_RTTIME)
  1702. # define RLIMIT_RTTIME (RLIMIT_RTPRIO + 1)
  1703. # endif
  1704. # endif
  1705. struct limits limits[] =
  1706. {
  1707. # ifdef RLIMIT_CPU
  1708. { RLIMIT_CPU, "cputime", 1, "seconds" },
  1709. # endif /* RLIMIT_CPU */
  1710. # ifdef RLIMIT_FSIZE
  1711. # ifndef aiws
  1712. { RLIMIT_FSIZE, "filesize", 1024, "kbytes" },
  1713. # else
  1714. { RLIMIT_FSIZE, "filesize", 512, "blocks" },
  1715. # endif /* aiws */
  1716. # endif /* RLIMIT_FSIZE */
  1717. # ifdef RLIMIT_DATA
  1718. { RLIMIT_DATA, "datasize", 1024, "kbytes" },
  1719. # endif /* RLIMIT_DATA */
  1720. # ifdef RLIMIT_STACK
  1721. # ifndef aiws
  1722. { RLIMIT_STACK, "stacksize", 1024, "kbytes" },
  1723. # else
  1724. { RLIMIT_STACK, "stacksize", 1024 * 1024, "kbytes"},
  1725. # endif /* aiws */
  1726. # endif /* RLIMIT_STACK */
  1727. # ifdef RLIMIT_CORE
  1728. { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" },
  1729. # endif /* RLIMIT_CORE */
  1730. # ifdef RLIMIT_RSS
  1731. { RLIMIT_RSS, "memoryuse", 1024, "kbytes" },
  1732. # endif /* RLIMIT_RSS */
  1733. # ifdef RLIMIT_UMEM
  1734. { RLIMIT_UMEM, "memoryuse", 1024, "kbytes" },
  1735. # endif /* RLIMIT_UMEM */
  1736. # ifdef RLIMIT_VMEM
  1737. { RLIMIT_VMEM, "vmemoryuse", 1024, "kbytes" },
  1738. # endif /* RLIMIT_VMEM */
  1739. # if defined(RLIMIT_HEAP) /* found on BS2000/OSD systems */
  1740. { RLIMIT_HEAP, "heapsize", 1024, "kbytes" },
  1741. # endif /* RLIMIT_HEAP */
  1742. # ifdef RLIMIT_NOFILE
  1743. { RLIMIT_NOFILE, "descriptors", 1, "" },
  1744. # endif /* RLIMIT_NOFILE */
  1745. # ifdef RLIMIT_CONCUR
  1746. { RLIMIT_CONCUR, "concurrency", 1, "thread(s)" },
  1747. # endif /* RLIMIT_CONCUR */
  1748. # ifdef RLIMIT_MEMLOCK
  1749. { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" },
  1750. # endif /* RLIMIT_MEMLOCK */
  1751. # ifdef RLIMIT_NPROC
  1752. { RLIMIT_NPROC, "maxproc", 1, "" },
  1753. # endif /* RLIMIT_NPROC */
  1754. # if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
  1755. { RLIMIT_OFILE, "openfiles", 1, "" },
  1756. # endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */
  1757. # ifdef RLIMIT_SBSIZE
  1758. { RLIMIT_SBSIZE, "sbsize", 1, "" },
  1759. # endif /* RLIMIT_SBSIZE */
  1760. # ifdef RLIMIT_SWAP
  1761. { RLIMIT_SWAP, "swapsize", 1024, "kbytes" },
  1762. # endif /* RLIMIT_SWAP */
  1763. # ifdef RLIMIT_LOCKS
  1764. { RLIMIT_LOCKS, "maxlocks", 1, "" },
  1765. # endif /* RLIMIT_LOCKS */
  1766. # ifdef RLIMIT_SIGPENDING
  1767. { RLIMIT_SIGPENDING,"maxsignal", 1, "" },
  1768. # endif /* RLIMIT_SIGPENDING */
  1769. # ifdef RLIMIT_MSGQUEUE
  1770. { RLIMIT_MSGQUEUE, "maxmessage", 1, "" },
  1771. # endif /* RLIMIT_MSGQUEUE */
  1772. # ifdef RLIMIT_NICE
  1773. { RLIMIT_NICE, "maxnice", 1, "" },
  1774. # endif /* RLIMIT_NICE */
  1775. # ifdef RLIMIT_RTPRIO
  1776. { RLIMIT_RTPRIO, "maxrtprio", 1, "" },
  1777. # endif /* RLIMIT_RTPRIO */
  1778. # ifdef RLIMIT_RTTIME
  1779. { RLIMIT_RTTIME, "maxrttime", 1, "usec" },
  1780. # endif /* RLIMIT_RTTIME */
  1781. { -1, NULL, 0, NULL }
  1782. };
  1783. static struct limits *findlim (Char *);
  1784. static RLIM_TYPE getval (struct limits *, Char **);
  1785. static int strtail (Char *, const char *);
  1786. static void limtail (Char *, const char *);
  1787. static void limtail2 (Char *, const char *, const char *);
  1788. static void plim (struct limits *, int);
  1789. static int setlim (struct limits *, int, RLIM_TYPE);
  1790. #ifdef convex
  1791. static RLIM_TYPE
  1792. restrict_limit(double value)
  1793. {
  1794. /*
  1795. * is f too large to cope with? return the maximum or minimum int
  1796. */
  1797. if (value > (double) INT_MAX)
  1798. return (RLIM_TYPE) INT_MAX;
  1799. else if (value < (double) INT_MIN)
  1800. return (RLIM_TYPE) INT_MIN;
  1801. else
  1802. return (RLIM_TYPE) value;
  1803. }
  1804. #else /* !convex */
  1805. # define restrict_limit(x) ((RLIM_TYPE) (x))
  1806. #endif /* convex */
  1807. static struct limits *
  1808. findlim(Char *cp)
  1809. {
  1810. struct limits *lp, *res;
  1811. res = NULL;
  1812. for (lp = limits; lp->limconst >= 0; lp++)
  1813. if (prefix(cp, str2short(lp->limname))) {
  1814. if (res)
  1815. stderror(ERR_NAME | ERR_AMBIG);
  1816. res = lp;
  1817. }
  1818. if (res)
  1819. return (res);
  1820. stderror(ERR_NAME | ERR_LIMIT);
  1821. /* NOTREACHED */
  1822. return (0);
  1823. }
  1824. /*ARGSUSED*/
  1825. void
  1826. dolimit(Char **v, struct command *c)
  1827. {
  1828. struct limits *lp;
  1829. RLIM_TYPE limit;
  1830. int hard = 0;
  1831. USE(c);
  1832. v++;
  1833. if (*v && eq(*v, STRmh)) {
  1834. hard = 1;
  1835. v++;
  1836. }
  1837. if (*v == 0) {
  1838. for (lp = limits; lp->limconst >= 0; lp++)
  1839. plim(lp, hard);
  1840. return;
  1841. }
  1842. lp = findlim(v[0]);
  1843. if (v[1] == 0) {
  1844. plim(lp, hard);
  1845. return;
  1846. }
  1847. limit = getval(lp, v + 1);
  1848. if (setlim(lp, hard, limit) < 0)
  1849. stderror(ERR_SILENT);
  1850. }
  1851. static RLIM_TYPE
  1852. getval(struct limits *lp, Char **v)
  1853. {
  1854. float f;
  1855. Char *cp = *v++;
  1856. f = atof(short2str(cp));
  1857. # ifdef convex
  1858. /*
  1859. * is f too large to cope with. limit f to minint, maxint - X-6768 by
  1860. * strike
  1861. */
  1862. if ((f < (double) INT_MIN) || (f > (double) INT_MAX)) {
  1863. stderror(ERR_NAME | ERR_TOOLARGE);
  1864. }
  1865. # endif /* convex */
  1866. while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
  1867. cp++;
  1868. if (*cp == 0) {
  1869. if (*v == 0)
  1870. return restrict_limit((f * lp->limdiv) + 0.5);
  1871. cp = *v;
  1872. }
  1873. switch (*cp) {
  1874. # ifdef RLIMIT_CPU
  1875. case ':':
  1876. if (lp->limconst != RLIMIT_CPU)
  1877. goto badscal;
  1878. return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f * 60.0 + atof(short2str(cp + 1))));
  1879. case 'h':
  1880. if (lp->limconst != RLIMIT_CPU)
  1881. goto badscal;
  1882. limtail(cp, "hours");
  1883. f *= 3600.0;
  1884. break;
  1885. # endif /* RLIMIT_CPU */
  1886. case 'm':
  1887. # ifdef RLIMIT_CPU
  1888. if (lp->limconst == RLIMIT_CPU) {
  1889. limtail(cp, "minutes");
  1890. f *= 60.0;
  1891. break;
  1892. }
  1893. # endif /* RLIMIT_CPU */
  1894. limtail2(cp, "megabytes", "mbytes");
  1895. f *= 1024.0 * 1024.0;
  1896. break;
  1897. # ifdef RLIMIT_CPU
  1898. case 's':
  1899. if (lp->limconst != RLIMIT_CPU)
  1900. goto badscal;
  1901. limtail(cp, "seconds");
  1902. break;
  1903. # endif /* RLIMIT_CPU */
  1904. case 'G':
  1905. *cp = 'g';
  1906. /*FALLTHROUGH*/
  1907. case 'g':
  1908. # ifdef RLIMIT_CPU
  1909. if (lp->limconst == RLIMIT_CPU)
  1910. goto badscal;
  1911. # endif /* RLIMIT_CPU */
  1912. limtail2(cp, "gigabytes", "gbytes");
  1913. f *= 1024.0 * 1024.0 * 1024.0;
  1914. break;
  1915. case 'M':
  1916. # ifdef RLIMIT_CPU
  1917. if (lp->limconst == RLIMIT_CPU)
  1918. goto badscal;
  1919. # endif /* RLIMIT_CPU */
  1920. *cp = 'm';
  1921. limtail2(cp, "megabytes", "mbytes");
  1922. f *= 1024.0 * 1024.0;
  1923. break;
  1924. case 'k':
  1925. # ifdef RLIMIT_CPU
  1926. if (lp->limconst == RLIMIT_CPU)
  1927. goto badscal;
  1928. # endif /* RLIMIT_CPU */
  1929. limtail2(cp, "kilobytes", "kbytes");
  1930. f *= 1024.0;
  1931. break;
  1932. case 'b':
  1933. # ifdef RLIMIT_CPU
  1934. if (lp->limconst == RLIMIT_CPU)
  1935. goto badscal;
  1936. # endif /* RLIMIT_CPU */
  1937. limtail(cp, "blocks");
  1938. f *= 512.0;
  1939. break;
  1940. case 'u':
  1941. limtail(cp, "unlimited");
  1942. return ((RLIM_TYPE) RLIM_INFINITY);
  1943. default:
  1944. # ifdef RLIMIT_CPU
  1945. badscal:
  1946. # endif /* RLIMIT_CPU */
  1947. stderror(ERR_NAME | ERR_SCALEF);
  1948. }
  1949. # ifdef convex
  1950. return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f + 0.5));
  1951. # else
  1952. f += 0.5;
  1953. if (f > (float) ((RLIM_TYPE) RLIM_INFINITY))
  1954. return ((RLIM_TYPE) RLIM_INFINITY);
  1955. else
  1956. return ((RLIM_TYPE) f);
  1957. # endif /* convex */
  1958. }
  1959. static int
  1960. strtail(Char *cp, const char *str)
  1961. {
  1962. while (*cp && *cp == (Char)*str)
  1963. cp++, str++;
  1964. return (*cp != '\0');
  1965. }
  1966. static void
  1967. limtail(Char *cp, const char *str)
  1968. {
  1969. if (strtail(cp, str))
  1970. stderror(ERR_BADSCALE, str);
  1971. }
  1972. static void
  1973. limtail2(Char *cp, const char *str1, const char *str2)
  1974. {
  1975. if (strtail(cp, str1) && strtail(cp, str2))
  1976. stderror(ERR_BADSCALE, str1);
  1977. }
  1978. /*ARGSUSED*/
  1979. static void
  1980. plim(struct limits *lp, int hard)
  1981. {
  1982. # ifdef BSDLIMIT
  1983. struct rlimit rlim;
  1984. # endif /* BSDLIMIT */
  1985. RLIM_TYPE limit;
  1986. int xdiv = lp->limdiv;
  1987. xprintf("%-13.13s", lp->limname);
  1988. # ifndef BSDLIMIT
  1989. limit = ulimit(lp->limconst, 0);
  1990. # ifdef aiws
  1991. if (lp->limconst == RLIMIT_DATA)
  1992. limit -= 0x20000000;
  1993. # endif /* aiws */
  1994. # else /* BSDLIMIT */
  1995. (void) getrlimit(lp->limconst, &rlim);
  1996. limit = hard ? rlim.rlim_max : rlim.rlim_cur;
  1997. # endif /* BSDLIMIT */
  1998. # if !defined(BSDLIMIT) || defined(FILESIZE512)
  1999. /*
  2000. * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024
  2001. * blocks. Note we cannot pre-multiply cause we might overflow (A/UX)
  2002. */
  2003. if (lp->limconst == RLIMIT_FSIZE) {
  2004. if (limit >= (RLIM_INFINITY / 512))
  2005. limit = RLIM_INFINITY;
  2006. else
  2007. xdiv = (xdiv == 1024 ? 2 : 1);
  2008. }
  2009. # endif /* !BSDLIMIT || FILESIZE512 */
  2010. if (limit == RLIM_INFINITY)
  2011. xprintf("unlimited");
  2012. else
  2013. # if defined(RLIMIT_CPU) && defined(_OSD_POSIX)
  2014. if (lp->limconst == RLIMIT_CPU &&
  2015. (unsigned long)limit >= 0x7ffffffdUL)
  2016. xprintf("unlimited");
  2017. else
  2018. # endif
  2019. # ifdef RLIMIT_CPU
  2020. if (lp->limconst == RLIMIT_CPU)
  2021. psecs(limit);
  2022. else
  2023. # endif /* RLIMIT_CPU */
  2024. xprintf("%ld %s", (long) (limit / xdiv), lp->limscale);
  2025. xputchar('\n');
  2026. }
  2027. /*ARGSUSED*/
  2028. void
  2029. dounlimit(Char **v, struct command *c)
  2030. {
  2031. struct limits *lp;
  2032. int lerr = 0;
  2033. int hard = 0;
  2034. int force = 0;
  2035. USE(c);
  2036. while (*++v && **v == '-') {
  2037. Char *vp = *v;
  2038. while (*++vp)
  2039. switch (*vp) {
  2040. case 'f':
  2041. force = 1;
  2042. break;
  2043. case 'h':
  2044. hard = 1;
  2045. break;
  2046. default:
  2047. stderror(ERR_ULIMUS);
  2048. break;
  2049. }
  2050. }
  2051. if (*v == 0) {
  2052. for (lp = limits; lp->limconst >= 0; lp++)
  2053. if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
  2054. lerr++;
  2055. if (!force && lerr)
  2056. stderror(ERR_SILENT);
  2057. return;
  2058. }
  2059. while (*v) {
  2060. lp = findlim(*v++);
  2061. if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0 && !force)
  2062. stderror(ERR_SILENT);
  2063. }
  2064. }
  2065. static int
  2066. setlim(struct limits *lp, int hard, RLIM_TYPE limit)
  2067. {
  2068. # ifdef BSDLIMIT
  2069. struct rlimit rlim;
  2070. (void) getrlimit(lp->limconst, &rlim);
  2071. # ifdef FILESIZE512
  2072. /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */
  2073. if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE)
  2074. limit /= 512;
  2075. # endif /* FILESIZE512 */
  2076. if (hard)
  2077. rlim.rlim_max = limit;
  2078. else if (limit == RLIM_INFINITY && euid != 0)
  2079. rlim.rlim_cur = rlim.rlim_max;
  2080. else
  2081. rlim.rlim_cur = limit;
  2082. if (rlim.rlim_cur > rlim.rlim_max)
  2083. rlim.rlim_max = rlim.rlim_cur;
  2084. if (setrlimit(lp->limconst, &rlim) < 0) {
  2085. # else /* BSDLIMIT */
  2086. if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE)
  2087. limit /= 512;
  2088. # ifdef aiws
  2089. if (lp->limconst == RLIMIT_DATA)
  2090. limit += 0x20000000;
  2091. # endif /* aiws */
  2092. if (ulimit(toset(lp->limconst), limit) < 0) {
  2093. # endif /* BSDLIMIT */
  2094. int err;
  2095. char *op, *type;
  2096. err = errno;
  2097. op = strsave(limit == RLIM_INFINITY ? CGETS(15, 2, "remove") :
  2098. CGETS(15, 3, "set"));
  2099. cleanup_push(op, xfree);
  2100. type = strsave(hard ? CGETS(15, 4, " hard") : "");
  2101. cleanup_push(type, xfree);
  2102. xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname,
  2103. lp->limname, op, type, strerror(err));
  2104. cleanup_until(op);
  2105. return (-1);
  2106. }
  2107. return (0);
  2108. }
  2109. #endif /* !HAVENOLIMIT */
  2110. /*ARGSUSED*/
  2111. void
  2112. dosuspend(Char **v, struct command *c)
  2113. {
  2114. #ifdef BSDJOBS
  2115. struct sigaction old;
  2116. #endif /* BSDJOBS */
  2117. USE(c);
  2118. USE(v);
  2119. if (loginsh)
  2120. stderror(ERR_SUSPLOG);
  2121. untty();
  2122. #ifdef BSDJOBS
  2123. sigaction(SIGTSTP, NULL, &old);
  2124. signal(SIGTSTP, SIG_DFL);
  2125. (void) kill(0, SIGTSTP);
  2126. /* the shell stops here */
  2127. sigaction(SIGTSTP, &old, NULL);
  2128. #else /* !BSDJOBS */
  2129. stderror(ERR_JOBCONTROL);
  2130. #endif /* BSDJOBS */
  2131. #ifdef BSDJOBS
  2132. if (tpgrp != -1) {
  2133. if (grabpgrp(FSHTTY, opgrp) == -1)
  2134. stderror(ERR_SYSTEM, "tcgetpgrp", strerror(errno));
  2135. (void) setpgid(0, shpgrp);
  2136. (void) tcsetpgrp(FSHTTY, shpgrp);
  2137. }
  2138. #endif /* BSDJOBS */
  2139. (void) setdisc(FSHTTY);
  2140. }
  2141. /* This is the dreaded EVAL built-in.
  2142. * If you don't fiddle with file descriptors, and reset didfds,
  2143. * this command will either ignore redirection inside or outside
  2144. * its arguments, e.g. eval "date >x" vs. eval "date" >x
  2145. * The stuff here seems to work, but I did it by trial and error rather
  2146. * than really knowing what was going on. If tpgrp is zero, we are
  2147. * probably a background eval, e.g. "eval date &", and we want to
  2148. * make sure that any processes we start stay in our pgrp.
  2149. * This is also the case for "time eval date" -- stay in same pgrp.
  2150. * Otherwise, under stty tostop, processes will stop in the wrong
  2151. * pgrp, with no way for the shell to get them going again. -IAN!
  2152. */
  2153. struct doeval_state
  2154. {
  2155. Char **evalvec, *evalp;
  2156. int didfds;
  2157. #ifndef CLOSE_ON_EXEC
  2158. int didcch;
  2159. #endif
  2160. int saveIN, saveOUT, saveDIAG;
  2161. int SHIN, SHOUT, SHDIAG;
  2162. };
  2163. static void
  2164. doeval_cleanup(void *xstate)
  2165. {
  2166. struct doeval_state *state;
  2167. state = xstate;
  2168. evalvec = state->evalvec;
  2169. evalp = state->evalp;
  2170. doneinp = 0;
  2171. #ifndef CLOSE_ON_EXEC
  2172. didcch = state->didcch;
  2173. #endif /* CLOSE_ON_EXEC */
  2174. didfds = state->didfds;
  2175. xclose(SHIN);
  2176. xclose(SHOUT);
  2177. xclose(SHDIAG);
  2178. close_on_exec(SHIN = dmove(state->saveIN, state->SHIN), 1);
  2179. close_on_exec(SHOUT = dmove(state->saveOUT, state->SHOUT), 1);
  2180. close_on_exec(SHDIAG = dmove(state->saveDIAG, state->SHDIAG), 1);
  2181. }
  2182. static Char **Ggv;
  2183. /*ARGSUSED*/
  2184. void
  2185. doeval(Char **v, struct command *c)
  2186. {
  2187. struct doeval_state state;
  2188. int gflag, my_reenter;
  2189. Char **gv;
  2190. jmp_buf_t osetexit;
  2191. USE(c);
  2192. v++;
  2193. if (*v == 0)
  2194. return;
  2195. gflag = tglob(v);
  2196. if (gflag) {
  2197. gv = v = globall(v, gflag);
  2198. if (v == 0)
  2199. stderror(ERR_NOMATCH);
  2200. cleanup_push(gv, blk_cleanup);
  2201. v = copyblk(v);
  2202. }
  2203. else {
  2204. gv = NULL;
  2205. v = copyblk(v);
  2206. trim(v);
  2207. }
  2208. Ggv = gv;
  2209. state.evalvec = evalvec;
  2210. state.evalp = evalp;
  2211. state.didfds = didfds;
  2212. #ifndef CLOSE_ON_EXEC
  2213. state.didcch = didcch;
  2214. #endif /* CLOSE_ON_EXEC */
  2215. state.SHIN = SHIN;
  2216. state.SHOUT = SHOUT;
  2217. state.SHDIAG = SHDIAG;
  2218. (void)close_on_exec(state.saveIN = dcopy(SHIN, -1), 1);
  2219. (void)close_on_exec(state.saveOUT = dcopy(SHOUT, -1), 1);
  2220. (void)close_on_exec(state.saveDIAG = dcopy(SHDIAG, -1), 1);
  2221. cleanup_push(&state, doeval_cleanup);
  2222. getexit(osetexit);
  2223. /* PWP: setjmp/longjmp bugfix for optimizing compilers */
  2224. #ifdef cray
  2225. my_reenter = 1; /* assume non-zero return val */
  2226. if (setexit() == 0) {
  2227. my_reenter = 0; /* Oh well, we were wrong */
  2228. #else /* !cray */
  2229. if ((my_reenter = setexit()) == 0) {
  2230. #endif /* cray */
  2231. evalvec = v;
  2232. evalp = 0;
  2233. (void)close_on_exec(SHIN = dcopy(0, -1), 1);
  2234. (void)close_on_exec(SHOUT = dcopy(1, -1), 1);
  2235. (void)close_on_exec(SHDIAG = dcopy(2, -1), 1);
  2236. #ifndef CLOSE_ON_EXEC
  2237. didcch = 0;
  2238. #endif /* CLOSE_ON_EXEC */
  2239. didfds = 0;
  2240. gv = Ggv;
  2241. process(0);
  2242. Ggv = gv;
  2243. }
  2244. if (my_reenter == 0) {
  2245. cleanup_until(&state);
  2246. if (Ggv)
  2247. cleanup_until(Ggv);
  2248. }
  2249. resexit(osetexit);
  2250. if (my_reenter)
  2251. stderror(ERR_SILENT);
  2252. }
  2253. /*************************************************************************/
  2254. /* print list of builtin commands */
  2255. static void
  2256. lbuffed_cleanup (void *dummy)
  2257. {
  2258. USE(dummy);
  2259. lbuffed = 1;
  2260. }
  2261. /*ARGSUSED*/
  2262. void
  2263. dobuiltins(Char **v, struct command *c)
  2264. {
  2265. /* would use print_by_column() in tw.parse.c but that assumes
  2266. * we have an array of Char * to pass.. (sg)
  2267. */
  2268. const struct biltins *b;
  2269. int row, col, columns, rows;
  2270. unsigned int w, maxwidth;
  2271. USE(c);
  2272. USE(v);
  2273. lbuffed = 0; /* turn off line buffering */
  2274. cleanup_push(&lbuffed, lbuffed_cleanup);
  2275. /* find widest string */
  2276. for (maxwidth = 0, b = bfunc; b < &bfunc[nbfunc]; ++b)
  2277. maxwidth = max(maxwidth, strlen(b->bname));
  2278. ++maxwidth; /* for space */
  2279. columns = (TermH + 1) / maxwidth; /* PWP: terminal size change */
  2280. if (!columns)
  2281. columns = 1;
  2282. rows = (nbfunc + (columns - 1)) / columns;
  2283. for (b = bfunc, row = 0; row < rows; row++) {
  2284. for (col = 0; col < columns; col++) {
  2285. if (b < &bfunc[nbfunc]) {
  2286. w = strlen(b->bname);
  2287. xprintf("%s", b->bname);
  2288. if (col < (columns - 1)) /* Not last column? */
  2289. for (; w < maxwidth; w++)
  2290. xputchar(' ');
  2291. ++b;
  2292. }
  2293. }
  2294. if (row < (rows - 1)) {
  2295. if (Tty_raw_mode)
  2296. xputchar('\r');
  2297. xputchar('\n');
  2298. }
  2299. }
  2300. #ifdef WINNT_NATIVE
  2301. nt_print_builtins(maxwidth);
  2302. #else
  2303. if (Tty_raw_mode)
  2304. xputchar('\r');
  2305. xputchar('\n');
  2306. #endif /* WINNT_NATIVE */
  2307. cleanup_until(&lbuffed); /* turn back on line buffering */
  2308. flush();
  2309. }
  2310. #ifdef NLS_CATALOGS
  2311. char *
  2312. xcatgets(nl_catd ctd, int set_id, int msg_id, const char *s)
  2313. {
  2314. char *res;
  2315. errno = 0;
  2316. while ((res = catgets(ctd, set_id, msg_id, s)) == s && errno == EINTR) {
  2317. handle_pending_signals();
  2318. errno = 0;
  2319. }
  2320. return res;
  2321. }
  2322. # if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
  2323. char *
  2324. iconv_catgets(nl_catd ctd, int set_id, int msg_id, const char *s)
  2325. {
  2326. static char *buf = NULL;
  2327. static size_t buf_size = 0;
  2328. char *orig, *dest, *p;
  2329. ICONV_CONST char *src;
  2330. size_t src_size, dest_size;
  2331. orig = xcatgets(ctd, set_id, msg_id, s);
  2332. if (catgets_iconv == (iconv_t)-1 || orig == s)
  2333. return orig;
  2334. src = orig;
  2335. src_size = strlen(src) + 1;
  2336. if (buf == NULL && (buf = xmalloc(buf_size = src_size + 32)) == NULL)
  2337. return orig;
  2338. dest = buf;
  2339. while (src_size != 0) {
  2340. dest_size = buf + buf_size - dest;
  2341. if (iconv(catgets_iconv, &src, &src_size, &dest, &dest_size)
  2342. == (size_t)-1) {
  2343. switch (errno) {
  2344. case E2BIG:
  2345. if ((p = xrealloc(buf, buf_size * 2)) == NULL)
  2346. return orig;
  2347. buf_size *= 2;
  2348. dest = p + (dest - buf);
  2349. buf = p;
  2350. break;
  2351. case EILSEQ: case EINVAL: default:
  2352. return orig;
  2353. }
  2354. }
  2355. }
  2356. return buf;
  2357. }
  2358. # endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
  2359. #endif /* NLS_CATALOGS */
  2360. void
  2361. nlsinit(void)
  2362. {
  2363. #ifdef NLS_CATALOGS
  2364. static const char default_catalog[] = "tcsh";
  2365. char *catalog = (char *)(intptr_t)default_catalog;
  2366. if (adrof(STRcatalog) != NULL)
  2367. catalog = xasprintf("tcsh.%s", short2str(varval(STRcatalog)));
  2368. #ifdef NL_CAT_LOCALE /* POSIX-compliant. */
  2369. /*
  2370. * Check if LC_MESSAGES is set in the environment and use it, if so.
  2371. * If not, fall back to the setting of LANG.
  2372. */
  2373. catd = catopen(catalog, tgetenv(STRLC_MESSAGES) ? NL_CAT_LOCALE : 0);
  2374. #else /* pre-POSIX */
  2375. # ifndef MCLoadBySet
  2376. # define MCLoadBySet 0
  2377. # endif
  2378. catd = catopen(catalog, MCLoadBySet);
  2379. #endif
  2380. if (catalog != default_catalog)
  2381. xfree(catalog);
  2382. #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
  2383. /* xcatgets (), not CGETS, the charset name should be in ASCII anyway. */
  2384. catgets_iconv = iconv_open (nl_langinfo (CODESET),
  2385. xcatgets(catd, 255, 1, "UTF-8"));
  2386. #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
  2387. #endif /* NLS_CATALOGS */
  2388. #ifdef WINNT_NATIVE
  2389. nls_dll_init();
  2390. #endif /* WINNT_NATIVE */
  2391. errinit(); /* init the errorlist in correct locale */
  2392. mesginit(); /* init the messages for signals */
  2393. dateinit(); /* init the messages for dates */
  2394. editinit(); /* init the editor messages */
  2395. terminit(); /* init the termcap messages */
  2396. }
  2397. void
  2398. nlsclose(void)
  2399. {
  2400. #ifdef NLS_CATALOGS
  2401. #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
  2402. if (catgets_iconv != (iconv_t)-1) {
  2403. iconv_close(catgets_iconv);
  2404. catgets_iconv = (iconv_t)-1;
  2405. }
  2406. #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
  2407. if (catd != (nl_catd)-1) {
  2408. /*
  2409. * catclose can call other functions which can call longjmp
  2410. * making us re-enter this code. Prevent infinite recursion
  2411. * by resetting catd. Problem reported and solved by:
  2412. * Gerhard Niklasch
  2413. */
  2414. nl_catd oldcatd = catd;
  2415. catd = (nl_catd)-1;
  2416. while (catclose(oldcatd) == -1 && errno == EINTR)
  2417. handle_pending_signals();
  2418. }
  2419. #endif /* NLS_CATALOGS */
  2420. }