/release/picobsd/tinyware/msh/sh1.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 953 lines · 790 code · 94 blank · 69 comment · 243 complexity · 1731b5c71adcb734258ff88f901f0b06 MD5 · raw file

  1. #define Extern extern
  2. #include <sys/types.h>
  3. #include <signal.h>
  4. #define _NSIG NSIG
  5. #include <errno.h>
  6. #include <setjmp.h>
  7. #include "sh.h"
  8. /* -------- sh.c -------- */
  9. /*
  10. * shell
  11. */
  12. /* #include "sh.h" */
  13. int intr;
  14. int inparse;
  15. char flags['z'-'a'+1];
  16. char *flag = flags-'a';
  17. char *elinep = line+sizeof(line)-5;
  18. char *null = "";
  19. int heedint =1;
  20. struct env e ={line, iostack, iostack-1,
  21. (xint *)NULL, FDBASE, (struct env *)NULL};
  22. extern char **environ; /* environment pointer */
  23. /*
  24. * default shell, search rules
  25. */
  26. char shellname[] = "/bin/sh";
  27. char search[] = ":/bin:/usr/bin";
  28. _PROTOTYPE(void (*qflag), (int)) = SIG_IGN;
  29. _PROTOTYPE(int main, (int argc, char **argv ));
  30. _PROTOTYPE(int newfile, (char *s ));
  31. _PROTOTYPE(static char *findeq, (char *cp ));
  32. _PROTOTYPE(static char *cclass, (char *p, int sub ));
  33. _PROTOTYPE(void initarea, (void));
  34. int main(argc, argv)
  35. int argc;
  36. register char **argv;
  37. {
  38. register int f;
  39. register char *s;
  40. int cflag;
  41. char *name, **ap;
  42. int (*iof)();
  43. initarea();
  44. if ((ap = environ) != NULL) {
  45. while (*ap)
  46. assign(*ap++, !COPYV);
  47. for (ap = environ; *ap;)
  48. export(lookup(*ap++));
  49. }
  50. closeall();
  51. areanum = 1;
  52. shell = lookup("SHELL");
  53. if (shell->value == null)
  54. setval(shell, shellname);
  55. export(shell);
  56. homedir = lookup("HOME");
  57. if (homedir->value == null)
  58. setval(homedir, "/");
  59. export(homedir);
  60. setval(lookup("$"), itoa(getpid(), 5));
  61. path = lookup("PATH");
  62. if (path->value == null)
  63. setval(path, search);
  64. export(path);
  65. ifs = lookup("IFS");
  66. if (ifs->value == null)
  67. setval(ifs, " \t\n");
  68. prompt = lookup("PS1");
  69. if (prompt->value == null)
  70. #ifndef UNIXSHELL
  71. setval(prompt, "$ ");
  72. #else
  73. setval(prompt, "% ");
  74. #endif
  75. if (geteuid() == 0) {
  76. setval(prompt, "# ");
  77. prompt->status &= ~EXPORT;
  78. }
  79. cprompt = lookup("PS2");
  80. if (cprompt->value == null)
  81. setval(cprompt, "> ");
  82. iof = filechar;
  83. cflag = 0;
  84. name = *argv++;
  85. if (--argc >= 1) {
  86. if(argv[0][0] == '-' && argv[0][1] != '\0') {
  87. for (s = argv[0]+1; *s; s++)
  88. switch (*s) {
  89. case 'c':
  90. prompt->status &= ~EXPORT;
  91. cprompt->status &= ~EXPORT;
  92. setval(prompt, "");
  93. setval(cprompt, "");
  94. cflag = 1;
  95. if (--argc > 0)
  96. PUSHIO(aword, *++argv, iof = nlchar);
  97. break;
  98. case 'q':
  99. qflag = SIG_DFL;
  100. break;
  101. case 's':
  102. /* standard input */
  103. break;
  104. case 't':
  105. prompt->status &= ~EXPORT;
  106. setval(prompt, "");
  107. iof = linechar;
  108. break;
  109. case 'i':
  110. talking++;
  111. default:
  112. if (*s>='a' && *s<='z')
  113. flag[*s]++;
  114. }
  115. } else {
  116. argv--;
  117. argc++;
  118. }
  119. if (iof == filechar && --argc > 0) {
  120. setval(prompt, "");
  121. setval(cprompt, "");
  122. prompt->status &= ~EXPORT;
  123. cprompt->status &= ~EXPORT;
  124. if (newfile(name = *++argv))
  125. exit(1);
  126. }
  127. }
  128. setdash();
  129. if (e.iop < iostack) {
  130. PUSHIO(afile, 0, iof);
  131. if (isatty(0) && isatty(1) && !cflag)
  132. talking++;
  133. }
  134. signal(SIGQUIT, qflag);
  135. if (name && name[0] == '-') {
  136. talking++;
  137. if ((f = open(".profile", 0)) >= 0)
  138. next(remap(f));
  139. if ((f = open("/etc/profile", 0)) >= 0)
  140. next(remap(f));
  141. }
  142. if (talking)
  143. signal(SIGTERM, sig);
  144. if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  145. signal(SIGINT, onintr);
  146. dolv = argv;
  147. dolc = argc;
  148. dolv[0] = name;
  149. if (dolc > 1)
  150. for (ap = ++argv; --argc > 0;)
  151. if (assign(*ap = *argv++, !COPYV))
  152. dolc--; /* keyword */
  153. else
  154. ap++;
  155. setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
  156. for (;;) {
  157. if (talking && e.iop <= iostack)
  158. prs(prompt->value);
  159. onecommand();
  160. }
  161. }
  162. void
  163. setdash()
  164. {
  165. register char *cp, c;
  166. char m['z'-'a'+1];
  167. cp = m;
  168. for (c='a'; c<='z'; c++)
  169. if (flag[c])
  170. *cp++ = c;
  171. *cp = 0;
  172. setval(lookup("-"), m);
  173. }
  174. int
  175. newfile(s)
  176. register char *s;
  177. {
  178. register f;
  179. if (strcmp(s, "-") != 0) {
  180. f = open(s, 0);
  181. if (f < 0) {
  182. prs(s);
  183. err(": cannot open");
  184. return(1);
  185. }
  186. } else
  187. f = 0;
  188. next(remap(f));
  189. return(0);
  190. }
  191. void
  192. onecommand()
  193. {
  194. register i;
  195. jmp_buf m1;
  196. while (e.oenv)
  197. quitenv();
  198. areanum = 1;
  199. freehere(areanum);
  200. freearea(areanum);
  201. garbage();
  202. wdlist = 0;
  203. iolist = 0;
  204. e.errpt = 0;
  205. e.linep = line;
  206. yynerrs = 0;
  207. multiline = 0;
  208. inparse = 1;
  209. intr = 0;
  210. execflg = 0;
  211. setjmp(failpt = m1); /* Bruce Evans' fix */
  212. if (setjmp(failpt = m1) || yyparse() || intr) {
  213. while (e.oenv)
  214. quitenv();
  215. scraphere();
  216. if (!talking && intr)
  217. leave();
  218. inparse = 0;
  219. intr = 0;
  220. return;
  221. }
  222. inparse = 0;
  223. brklist = 0;
  224. intr = 0;
  225. execflg = 0;
  226. if (!flag['n'])
  227. execute(outtree, NOPIPE, NOPIPE, 0);
  228. if (!talking && intr) {
  229. execflg = 0;
  230. leave();
  231. }
  232. if ((i = trapset) != 0) {
  233. trapset = 0;
  234. runtrap(i);
  235. }
  236. }
  237. void
  238. fail()
  239. {
  240. longjmp(failpt, 1);
  241. /* NOTREACHED */
  242. }
  243. void
  244. leave()
  245. {
  246. if (execflg)
  247. fail();
  248. scraphere();
  249. freehere(1);
  250. runtrap(0);
  251. exit(exstat);
  252. /* NOTREACHED */
  253. }
  254. void
  255. warn(s)
  256. register char *s;
  257. {
  258. if(*s) {
  259. prs(s);
  260. exstat = -1;
  261. }
  262. prs("\n");
  263. if (flag['e'])
  264. leave();
  265. }
  266. void
  267. err(s)
  268. char *s;
  269. {
  270. warn(s);
  271. if (flag['n'])
  272. return;
  273. if (!talking)
  274. leave();
  275. if (e.errpt)
  276. longjmp(e.errpt, 1);
  277. closeall();
  278. e.iop = e.iobase = iostack;
  279. }
  280. int
  281. newenv(f)
  282. int f;
  283. {
  284. register struct env *ep;
  285. if (f) {
  286. quitenv();
  287. return(1);
  288. }
  289. ep = (struct env *) space(sizeof(*ep));
  290. if (ep == NULL) {
  291. while (e.oenv)
  292. quitenv();
  293. fail();
  294. }
  295. *ep = e;
  296. e.oenv = ep;
  297. e.errpt = errpt;
  298. return(0);
  299. }
  300. void
  301. quitenv()
  302. {
  303. register struct env *ep;
  304. register fd;
  305. if ((ep = e.oenv) != NULL) {
  306. fd = e.iofd;
  307. e = *ep;
  308. /* should close `'d files */
  309. DELETE(ep);
  310. while (--fd >= e.iofd)
  311. close(fd);
  312. }
  313. }
  314. /*
  315. * Is any character from s1 in s2?
  316. */
  317. int
  318. anys(s1, s2)
  319. register char *s1, *s2;
  320. {
  321. while (*s1)
  322. if (any(*s1++, s2))
  323. return(1);
  324. return(0);
  325. }
  326. /*
  327. * Is character c in s?
  328. */
  329. int
  330. any(c, s)
  331. register int c;
  332. register char *s;
  333. {
  334. while (*s)
  335. if (*s++ == c)
  336. return(1);
  337. return(0);
  338. }
  339. char *
  340. putn(n)
  341. register int n;
  342. {
  343. return(itoa(n, -1));
  344. }
  345. char *
  346. itoa(u, n)
  347. register unsigned u;
  348. int n;
  349. {
  350. register char *cp;
  351. static char s[20];
  352. int m;
  353. m = 0;
  354. if (n < 0 && (int) u < 0) {
  355. m++;
  356. u = -u;
  357. }
  358. cp = s+sizeof(s);
  359. *--cp = 0;
  360. do {
  361. *--cp = u%10 + '0';
  362. u /= 10;
  363. } while (--n > 0 || u);
  364. if (m)
  365. *--cp = '-';
  366. return(cp);
  367. }
  368. void
  369. next(f)
  370. int f;
  371. {
  372. PUSHIO(afile, f, filechar);
  373. }
  374. void
  375. onintr(s)
  376. int s; /* ANSI C requires a parameter */
  377. {
  378. signal(SIGINT, onintr);
  379. intr = 1;
  380. if (talking) {
  381. if (inparse) {
  382. prs("\n");
  383. fail();
  384. }
  385. }
  386. else if (heedint) {
  387. execflg = 0;
  388. leave();
  389. }
  390. }
  391. int
  392. letter(c)
  393. register c;
  394. {
  395. return((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_');
  396. }
  397. int
  398. digit(c)
  399. register c;
  400. {
  401. return(c >= '0' && c <= '9');
  402. }
  403. int
  404. letnum(c)
  405. register c;
  406. {
  407. return(letter(c) || digit(c));
  408. }
  409. char *
  410. space(n)
  411. int n;
  412. {
  413. register char *cp;
  414. if ((cp = getcell(n)) == 0)
  415. err("out of string space");
  416. return(cp);
  417. }
  418. char *
  419. strsave(s, a)
  420. register char *s;
  421. int a;
  422. {
  423. register char *cp, *xp;
  424. if ((cp = space(strlen(s)+1)) != NULL) {
  425. setarea((char *)cp, a);
  426. for (xp = cp; (*xp++ = *s++) != '\0';)
  427. ;
  428. return(cp);
  429. }
  430. return("");
  431. }
  432. void
  433. xfree(s)
  434. register char *s;
  435. {
  436. DELETE(s);
  437. }
  438. /*
  439. * trap handling
  440. */
  441. void
  442. sig(i)
  443. register int i;
  444. {
  445. trapset = i;
  446. signal(i, sig);
  447. }
  448. void runtrap(i)
  449. int i;
  450. {
  451. char *trapstr;
  452. if ((trapstr = trap[i]) == NULL)
  453. return;
  454. if (i == 0)
  455. trap[i] = 0;
  456. RUN(aword, trapstr, nlchar);
  457. }
  458. /* -------- var.c -------- */
  459. /* #include "sh.h" */
  460. /*
  461. * Find the given name in the dictionary
  462. * and return its value. If the name was
  463. * not previously there, enter it now and
  464. * return a null value.
  465. */
  466. struct var *
  467. lookup(n)
  468. register char *n;
  469. {
  470. register struct var *vp;
  471. register char *cp;
  472. register int c;
  473. static struct var dummy;
  474. if (digit(*n)) {
  475. dummy.name = n;
  476. for (c = 0; digit(*n) && c < 1000; n++)
  477. c = c*10 + *n-'0';
  478. dummy.status = RONLY;
  479. dummy.value = c <= dolc? dolv[c]: null;
  480. return(&dummy);
  481. }
  482. for (vp = vlist; vp; vp = vp->next)
  483. if (eqname(vp->name, n))
  484. return(vp);
  485. cp = findeq(n);
  486. vp = (struct var *)space(sizeof(*vp));
  487. if (vp == 0 || (vp->name = space((int)(cp-n)+2)) == 0) {
  488. dummy.name = dummy.value = "";
  489. return(&dummy);
  490. }
  491. for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++)
  492. ;
  493. if (*cp == 0)
  494. *cp = '=';
  495. *++cp = 0;
  496. setarea((char *)vp, 0);
  497. setarea((char *)vp->name, 0);
  498. vp->value = null;
  499. vp->next = vlist;
  500. vp->status = GETCELL;
  501. vlist = vp;
  502. return(vp);
  503. }
  504. /*
  505. * give variable at `vp' the value `val'.
  506. */
  507. void
  508. setval(vp, val)
  509. struct var *vp;
  510. char *val;
  511. {
  512. nameval(vp, val, (char *)NULL);
  513. }
  514. /*
  515. * if name is not NULL, it must be
  516. * a prefix of the space `val',
  517. * and end with `='.
  518. * this is all so that exporting
  519. * values is reasonably painless.
  520. */
  521. void
  522. nameval(vp, val, name)
  523. register struct var *vp;
  524. char *val, *name;
  525. {
  526. register char *cp, *xp;
  527. char *nv;
  528. int fl;
  529. if (vp->status & RONLY) {
  530. for (xp = vp->name; *xp && *xp != '=';)
  531. putc(*xp++);
  532. err(" is read-only");
  533. return;
  534. }
  535. fl = 0;
  536. if (name == NULL) {
  537. xp = space(strlen(vp->name)+strlen(val)+2);
  538. if (xp == 0)
  539. return;
  540. /* make string: name=value */
  541. setarea((char *)xp, 0);
  542. name = xp;
  543. for (cp = vp->name; (*xp = *cp++) && *xp!='='; xp++)
  544. ;
  545. if (*xp++ == 0)
  546. xp[-1] = '=';
  547. nv = xp;
  548. for (cp = val; (*xp++ = *cp++) != '\0';)
  549. ;
  550. val = nv;
  551. fl = GETCELL;
  552. }
  553. if (vp->status & GETCELL)
  554. xfree(vp->name); /* form new string `name=value' */
  555. vp->name = name;
  556. vp->value = val;
  557. vp->status |= fl;
  558. }
  559. void
  560. export(vp)
  561. struct var *vp;
  562. {
  563. vp->status |= EXPORT;
  564. }
  565. void
  566. ronly(vp)
  567. struct var *vp;
  568. {
  569. if (letter(vp->name[0])) /* not an internal symbol ($# etc) */
  570. vp->status |= RONLY;
  571. }
  572. int
  573. isassign(s)
  574. register char *s;
  575. {
  576. if (!letter((int)*s))
  577. return(0);
  578. for (; *s != '='; s++)
  579. if (*s == 0 || !letnum(*s))
  580. return(0);
  581. return(1);
  582. }
  583. int
  584. assign(s, cf)
  585. register char *s;
  586. int cf;
  587. {
  588. register char *cp;
  589. struct var *vp;
  590. if (!letter(*s))
  591. return(0);
  592. for (cp = s; *cp != '='; cp++)
  593. if (*cp == 0 || !letnum(*cp))
  594. return(0);
  595. vp = lookup(s);
  596. nameval(vp, ++cp, cf == COPYV? (char *)NULL: s);
  597. if (cf != COPYV)
  598. vp->status &= ~GETCELL;
  599. return(1);
  600. }
  601. int
  602. checkname(cp)
  603. register char *cp;
  604. {
  605. if (!letter(*cp++))
  606. return(0);
  607. while (*cp)
  608. if (!letnum(*cp++))
  609. return(0);
  610. return(1);
  611. }
  612. void
  613. putvlist(f, out)
  614. register int f, out;
  615. {
  616. register struct var *vp;
  617. for (vp = vlist; vp; vp = vp->next)
  618. if (vp->status & f && letter(*vp->name)) {
  619. if (vp->status & EXPORT)
  620. write(out, "export ", 7);
  621. if (vp->status & RONLY)
  622. write(out, "readonly ", 9);
  623. write(out, vp->name, (int)(findeq(vp->name) - vp->name));
  624. write(out, "\n", 1);
  625. }
  626. }
  627. int
  628. eqname(n1, n2)
  629. register char *n1, *n2;
  630. {
  631. for (; *n1 != '=' && *n1 != 0; n1++)
  632. if (*n2++ != *n1)
  633. return(0);
  634. return(*n2 == 0 || *n2 == '=');
  635. }
  636. static char *
  637. findeq(cp)
  638. register char *cp;
  639. {
  640. while (*cp != '\0' && *cp != '=')
  641. cp++;
  642. return(cp);
  643. }
  644. /* -------- gmatch.c -------- */
  645. /*
  646. * int gmatch(string, pattern)
  647. * char *string, *pattern;
  648. *
  649. * Match a pattern as in sh(1).
  650. */
  651. #define CMASK 0377
  652. #define QUOTE 0200
  653. #define QMASK (CMASK&~QUOTE)
  654. #define NOT '!' /* might use ^ */
  655. int
  656. gmatch(s, p)
  657. register char *s, *p;
  658. {
  659. register int sc, pc;
  660. if (s == NULL || p == NULL)
  661. return(0);
  662. while ((pc = *p++ & CMASK) != '\0') {
  663. sc = *s++ & QMASK;
  664. switch (pc) {
  665. case '[':
  666. if ((p = cclass(p, sc)) == NULL)
  667. return(0);
  668. break;
  669. case '?':
  670. if (sc == 0)
  671. return(0);
  672. break;
  673. case '*':
  674. s--;
  675. do {
  676. if (*p == '\0' || gmatch(s, p))
  677. return(1);
  678. } while (*s++ != '\0');
  679. return(0);
  680. default:
  681. if (sc != (pc&~QUOTE))
  682. return(0);
  683. }
  684. }
  685. return(*s == 0);
  686. }
  687. static char *
  688. cclass(p, sub)
  689. register char *p;
  690. register int sub;
  691. {
  692. register int c, d, not, found;
  693. if ((not = *p == NOT) != 0)
  694. p++;
  695. found = not;
  696. do {
  697. if (*p == '\0')
  698. return((char *)NULL);
  699. c = *p & CMASK;
  700. if (p[1] == '-' && p[2] != ']') {
  701. d = p[2] & CMASK;
  702. p++;
  703. } else
  704. d = c;
  705. if (c == sub || (c <= sub && sub <= d))
  706. found = !not;
  707. } while (*++p != ']');
  708. return(found? p+1: (char *)NULL);
  709. }
  710. /* -------- area.c -------- */
  711. #define REGSIZE sizeof(struct region)
  712. #define GROWBY 256
  713. #undef SHRINKBY 64
  714. #define FREE 32767
  715. #define BUSY 0
  716. #define ALIGN (sizeof(int)-1)
  717. /* #include "area.h" */
  718. struct region {
  719. struct region *next;
  720. int area;
  721. };
  722. /*
  723. * All memory between (char *)areabot and (char *)(areatop+1) is
  724. * exclusively administered by the area management routines.
  725. * It is assumed that sbrk() and brk() manipulate the high end.
  726. */
  727. static struct region *areabot; /* bottom of area */
  728. static struct region *areatop; /* top of area */
  729. static struct region *areanxt; /* starting point of scan */
  730. void
  731. initarea()
  732. {
  733. while ((int)sbrk(0) & ALIGN)
  734. sbrk(1);
  735. areabot = (struct region *)sbrk(REGSIZE);
  736. areabot->next = areabot;
  737. areabot->area = BUSY;
  738. areatop = areabot;
  739. areanxt = areabot;
  740. }
  741. char *
  742. getcell(nbytes)
  743. unsigned nbytes;
  744. {
  745. register int nregio;
  746. register struct region *p, *q;
  747. register i;
  748. if (nbytes == 0)
  749. abort(); /* silly and defeats the algorithm */
  750. /*
  751. * round upwards and add administration area
  752. */
  753. nregio = (nbytes+(REGSIZE-1))/REGSIZE + 1;
  754. for (p = areanxt;;) {
  755. if (p->area > areanum) {
  756. /*
  757. * merge free cells
  758. */
  759. while ((q = p->next)->area > areanum && q != areanxt)
  760. p->next = q->next;
  761. /*
  762. * exit loop if cell big enough
  763. */
  764. if (q >= p + nregio)
  765. goto found;
  766. }
  767. p = p->next;
  768. if (p == areanxt)
  769. break;
  770. }
  771. i = nregio >= GROWBY ? nregio : GROWBY;
  772. p = (struct region *)sbrk(i * REGSIZE);
  773. if (p == (struct region *)-1)
  774. return((char *)NULL);
  775. p--;
  776. if (p != areatop)
  777. abort(); /* allocated areas are contiguous */
  778. q = p + i;
  779. p->next = q;
  780. p->area = FREE;
  781. q->next = areabot;
  782. q->area = BUSY;
  783. areatop = q;
  784. found:
  785. /*
  786. * we found a FREE area big enough, pointed to by 'p', and up to 'q'
  787. */
  788. areanxt = p + nregio;
  789. if (areanxt < q) {
  790. /*
  791. * split into requested area and rest
  792. */
  793. if (areanxt+1 > q)
  794. abort(); /* insufficient space left for admin */
  795. areanxt->next = q;
  796. areanxt->area = FREE;
  797. p->next = areanxt;
  798. }
  799. p->area = areanum;
  800. return((char *)(p+1));
  801. }
  802. void
  803. freecell(cp)
  804. char *cp;
  805. {
  806. register struct region *p;
  807. if ((p = (struct region *)cp) != NULL) {
  808. p--;
  809. if (p < areanxt)
  810. areanxt = p;
  811. p->area = FREE;
  812. }
  813. }
  814. void
  815. freearea(a)
  816. register int a;
  817. {
  818. register struct region *p, *top;
  819. top = areatop;
  820. for (p = areabot; p != top; p = p->next)
  821. if (p->area >= a)
  822. p->area = FREE;
  823. }
  824. void
  825. setarea(cp,a)
  826. char *cp;
  827. int a;
  828. {
  829. register struct region *p;
  830. if ((p = (struct region *)cp) != NULL)
  831. (p-1)->area = a;
  832. }
  833. int
  834. getarea(cp)
  835. char *cp;
  836. {
  837. return ((struct region*)cp-1)->area;
  838. }
  839. void
  840. garbage()
  841. {
  842. register struct region *p, *q, *top;
  843. top = areatop;
  844. for (p = areabot; p != top; p = p->next) {
  845. if (p->area > areanum) {
  846. while ((q = p->next)->area > areanum)
  847. p->next = q->next;
  848. areanxt = p;
  849. }
  850. }
  851. #ifdef SHRINKBY
  852. if (areatop >= q + SHRINKBY && q->area > areanum) {
  853. brk((char *)(q+1));
  854. q->next = areabot;
  855. q->area = BUSY;
  856. areatop = q;
  857. }
  858. #endif
  859. }